Skip to main content

InterchainAuthJS

Overview​

InterchainAuthJS is a JavaScript/TypeScript library that simplifies the process of composing and broadcasting messages for Cosmos and IBC-related modules. This package streamlines interactions with the Interchain Auth module, enabling developers to:

  • Compose messages: Easily create Cosmos SDK and IBC-compatible messages with full support for Protobuf and Amino encoding.
  • Type safety: Leverages TypeScript for robust type definitions across all supported modules.
  • Efficiency: Handles all underlying encoding complexities, letting developers focus on building their applications.

Built using Cosmos Kit Telescope, InterchainAuthJS provides pre-generated types and helper functions, ensuring compatibility with the Cosmos SDK and related ecosystems.

Installation​

you can install using npm or yarn

npm install @s16rv/interchainauthjs

Tutorials​

Connecting to RPC Client​

RPC clients allow you to interact with blockchain modules, such as Cosmos, IBC or Interchain Auth by querying data directly from the blockchain network. With an RPC client, you can retrieve information from various modules, including balances, pools, and more.

Creating Client​
rpc-client.ts
import { interchainauth } from '@s16rv/interchainauthjs';

const { createRPCQueryClient } = interchainauth.ClientFactory;
const client = await createRPCQueryClient({ rpcEndpoint: RPC_ENDPOINT });

Now you can query from the Cosmos, IBC or Interchain Auth modules.

Example: Querying Balances​
balance.ts
const balance = await client.cosmos.bank.v1beta1
.allBalances({ address: 'your_address' });
/*
return
{
"balances": [
{
"denom": "uatom",
"amount": "145925592"
}
],
"pagination": {
"next_key": null,
"total": "1"
}
}
*/
Example: Querying Transaction​
transaction.ts
const tx = await client.cosmos.tx.v1beta1.getTx({
txHash: 'your_tx_hash'
});
/*
return
{
"tx": {
"body": {
"messages": [
{
"@type": "/interchainauth.icauth.v1.MsgSubmitTx",
"sender": "cosmos1....",
"channel_id": "channel-1",
"msgs": [
...
}
*/

Connecting with Wallets & Signing Message​

In Cosmos-based dApps, connecting to a wallet is essential for signing and broadcasting transactions. You can achieve this using various libraries like:

Here, we focus on how to use Keplr for wallet connection and transaction signing, leveraging InterchainAuthJS for simplified client initialization.

Connecting to Keplr​

To interact with a Cosmos wallet, you need an OfflineSigner. This signer allows you to sign transactions securely. The signer can be retrieved from wallet extensions like Keplr.

wallet.ts
const {keplr} = window
if (!keplr) {
throw new Error("Keplr extension is not installed.");
}

const chainId= "your-chain-id"

//connecting to keplr
await keplr.enable(chainId);

//getting the signer
const signer = keplr.getOfflineSigner(chainId);
Initializing the Signing Client​

Use the getSigningInterchainauthClient method from InterchainAuthJS to create a SigningStargateClient. This client is preloaded with interchain-auth, cosmos, and IBC proto/amino message types, removing the need for manual configurations.

wallet.ts
import { getSigningInterchainauthClient } from '@s16rv/interchainauthjs';

const client = await getSigningInterchainauthClient({
rpcEndpoint: "your-rpc-endpoint",
signer, // OfflineSigner retrieved earlier
});

console.log("Signing client initialized!", client);
Sign and Broadcast Message​

Once you have the client, you can use it to sign and broadcast transactions.

Cosmos supports two signing methods:

  1. Direct Signing: Used for Protobuf-based signing (modern and efficient).
  2. Amino Signing: Used for legacy JSON-based signing (for compatibility with older modules like Authz).

You can initialize both signers and use them depending on the transaction requirements.

  • Step 1: Connect to Wallet

    wallet.ts
    async function connectWallet(chainId) {
    if (!window.keplr) {
    throw new Error("Keplr wallet not found!");
    }

    // Enable Keplr for the specific chain
    await window.keplr.enable(chainId);

    // Get OfflineDirectSigner and OfflineAminoSigner
    const offlineDirectSigner = await window.keplr.getOfflineSigner(chainId);
    const offlineAminoSigner = window.keplr.getOfflineSignerOnlyAmino(chainId);

    return { offlineDirectSigner, offlineAminoSigner };
    }
  • Step 2: Initialize Signing Client

    wallet.ts
    async function getClient(rpcEndpoint, offlineSigner) {
    const client = await getSigningInterchainauthClient({
    rpcEndpoint,
    signer: offlineSigner,
    });

    return client;
    }
  • Step 3: Sign and Broadcast Transactions

    wallet.ts
    async function signAndBroadcast(
    chainId,
    rpcEndpoint,
    txMsg,
    fee,
    memo,
    useAmino = false,
    ) {
    // Connect wallet and get appropriate signer
    const { offlineDirectSigner, offlineAminoSigner } = await connectWallet(
    chainId,
    );

    // Choose the signer type
    const offlineSigner = useAmino ? offlineAminoSigner : offlineDirectSigner;

    // Initialize the client with the selected signer
    const client = await getClient(rpcEndpoint, offlineSigner);

    // Broadcast the transaction
    const result = await client.signAndBroadcast(chainId, [txMsg], fee, memo);

    return result;
    }

Advanced Usage​

Manually composing signing client

wallet.ts
import { OfflineSigner, GeneratedType, Registry } from "@cosmjs/proto-signing";
import { AminoTypes, SigningStargateClient } from "@cosmjs/stargate";
import {
cosmosAminoConverters,
cosmosProtoRegistry,
ibcProtoRegistry,
ibcAminoConverters,
interchainauthAminoConverters,
interchainauthProtoRegistry,
} from "@s16rv/interchainauthjs";

const protoRegistry: ReadonlyArray<[string, GeneratedType]> = [
...cosmosProtoRegistry,
...ibcProtoRegistry,
...interchainauthProtoRegistry,
];

const aminoConverters = {
...cosmosAminoConverters,
...ibcAminoConverters,
...interchainauthAminoConverters,
};

const registry = new Registry(protoRegistry);
const aminoTypes = new AminoTypes(aminoConverters);

const stargateClient = await SigningStargateClient.connectWithSigner(
rpcEndpoint,
signer,
{
registry,
aminoTypes,
},
);

Composing Message​

Composing messages is a crucial part of interacting with blockchain networks. Messages represent actions such as sending tokens, delegating, or executing smart contracts. With InterchainAuthJS, composing messages is streamlined, supporting Cosmos modules and IBC messages out of the box.

Interchain Auth MsgSubmitTx​

The Interchain Auth MsgSubmitTx is used to submit interchain auth transaction.

  • Flexible Message Composition: Inside the msgs array, users can include any action from the Cosmos or IBC modules. This also supports multiple messages at once, provided the messages use the same channel.
  • No Extra Dependencies: Users can compose any message from the Cosmos or IBC module directly using InterchainAuthJS. There is no need to install additional packages for message composition.
MsgSubmitTx Interface​
Interface
{
sender: string; // The address initiating the transaction
channelId: string; // The IBC channel ID from port 'icauth'
msgs: EncodeObject[]; // List of EncodeObject messages
relativeTimeout: bigint; // Timeout in nanoseconds
memo?: string; // (Optional) transaction memo
}

There are two ways to generate this message using InterchainAuthJS.

Composing Message Using MessageComposer​

You can utilize the MessageComposer utility provided by InterchainAuthJS to compose a submitTx message easily.

message.ts
import { interchainauth } from "@s16rv/interchainauthjs";

const { submitTx } = interchainauth.icauth.v1.MessageComposer.withTypeUrl;

const msgSend = "Your-encoded-message-send";

const msg = submitTx({
sender: "cosmos1...",
channelId: "channel-0",
msgs: [msgSend],
relativeTimeout: BigInt(1800000000000),
memo: "Optional memo",
});
Composing Message Using MsgSubmitTx​

Alternatively, you can directly use the MsgSubmitTx type to compose your message. This provides a more low-level approach, allowing you to construct or encode messages manually.

  • Using MsgSubmitTx.fromPartial

    message.ts
    const msgSend = "Your-encoded-message-send";

    const value = MsgSubmitTx.fromPartial({
    sender: "cosmos1...",
    channelId: "channel-0",
    msgs: [msgSend],
    relativeTimeout: BigInt(1800000000000),
    memo: "Optional memo",
    });
    return {
    typeUrl: "/interchainauth.icauth.v1.MsgSubmitTx",
    value,
    };
  • Using MsgSubmitTx.encode

    If you need the binary-encoded format of the message, you can use the MsgSubmitTx.encode method:

    message.ts
    const msgSend = "Your-encoded-message-send";

    const value = MsgSubmitTx.encode({
    sender: "cosmos1...",
    channelId: "channel-0",
    msgs: [msgSend],
    relativeTimeout: BigInt(1800000000000),
    memo: "Optional memo",
    }).finish();
    return {
    typeUrl: "/interchainauth.icauth.v1.MsgSubmitTx",
    value,
    };

Example​

Send Tokens (Cosmos Bank Module)​
message.ts
import { MsgSend } from "@s16rv/interchainauthjs/dist/codegen/cosmos/bank/v1beta1/tx";

const sendMsg = {
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
value: MsgSend.encode({
fromAddress: "cosmos1...",
toAddress: "cosmos1recipient...",
amount: [{ denom: "uatom", amount: "1000000" }], // 1 ATOM
}).finish(),
};
IBC Transfer (IBC Transfer Module)​
message.ts
import { MsgTransfer } from '@s16rv/interchainauthjs/dist/codegen/ibc/applications/transfer/v1/tx';

const transferMsg = {
typeUrl: '/ibc.applications.transfer.v1.MsgTransfer'
value: MsgTransfer.encode({
sourcePort: 'transfer',
sourceChannel: 'channel-0',
token: { denom: 'uatom', amount: '1000000' }, // 1 ATOM
sender: 'cosmos1...',
receiver: 'cosmos1recipient...',
timeoutHeight: undefined, // Optional
timeoutTimestamp: Date.now() + 300000000000, // 5 minutes in nanoseconds
}).finish(),
}
Submit Tx (Interchain Auth Module)​

The send and transfer messages can be added to the msgs array when composing an Interchain Auth Submit Tx. For example:

message.ts
const msg = submitTx({
sender: "cosmos1...",
channelId: "channel-0",
msgs: [sendMsg, transferMsg],
relativeTimeout: BigInt(1800000000000),
memo: "Optional memo",
});
warning

The MsgSubmitTx may fail to execute under the following conditions:

  • Incorrect Channel ID: The channelId does not match the correct IBC channel for the specified action.
  • Mismatched Sender Address: The sender address in the message does not match the address of the signing wallet.
  • Invalid Message Format: The message is not properly encoded or is missing required fields.
  • Insufficient Gas or Fees: The transaction does not include enough gas or fees to cover the execution cost.
  • Expired Timeout: The timeoutTimestamp has already elapsed by the time the message is processed.

Checkout these related projects:

  • @cosmology/telescope Your Frontend Companion for Building with TypeScript with Cosmos SDK Modules.
  • @cosmwasm/ts-codegen Convert your CosmWasm smart contracts into dev-friendly TypeScript classes.
  • chain-registry Everything from token symbols, logos, and IBC denominations for all assets you want to support in your application.
  • cosmos-kit Experience the convenience of connecting with a variety of web3 wallets through a single, streamlined interface.
  • create-cosmos-app Set up a modern Cosmos app by running one command.
  • interchain-ui The Interchain Design System, empowering developers with a flexible, easy-to-use UI kit.
  • starship Unified Testing and Development for the Interchain.

Credits​

🛠 Built by Cosmology — if you like our tools, please consider delegating to our validator ⚛️

Disclaimer​

AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED “AS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.

No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.