Install the IBC tools

Begin by preparing the environment with the necessary binaries. The Inter-Blockchain Communication (IBC) protocol relies on ibc-go for the application layer and a relayer to handle packet forwarding between chains. For 2026, we assume a Docker-based workflow for consistency and isolation.

First, ensure Docker and Docker Compose are installed. Most developers use the official Docker Desktop or standard package managers like apt or brew. Verify the installation by running docker --version and docker compose version.

Next, install the ibc-go binaries. The Cosmos ecosystem provides pre-built binaries via GitHub releases or allows compilation from source. For most testing environments, pulling the latest stable release is sufficient.

Shell
# Install IBC-Go CLI tools
brew install cosmos/ibc/ibc-go

# Verify installation
ibc-go version

The relayer is the bridge that moves data. We recommend using hermes (the official CosmWasm-compatible relayer) or ibc-go's built-in relayer capabilities for simpler setups. Install the relayer binary next.

Shell
# Install the Hermes relayer
brew install hermes-relayer

# Verify installation
hermes version

With both ibc-go and the relayer installed, your environment is ready for connection setup. The next step involves configuring the paths and chains that will communicate.

Configure relayer connections

Before the relayer can move packets between chains, it needs to know where those chains live. You must define the chain IDs and RPC endpoints for both the source and destination networks in your relayer configuration file. This file acts as the map for your relayer, telling it which nodes to trust and which chain identifiers to use for packet forwarding.

Start by creating a new configuration file, typically named config.yaml or config.json, depending on your relayer implementation (such as hermes or ibc-go). The structure requires two main sections: one for each chain. Each section needs a unique chain_id that matches the genesis configuration of the network, an rpc_addr pointing to a healthy node, and an grpc_addr for querying state.

YAML
version: 1

type: cosmos
config:
  chain-1:
    id: cosmoshub-4
    rpc_addr: http://cosmoshub-rpc.example.com:26657
    grpc_addr: http://cosmoshub-grpc.example.com:9090
    account-prefix: cosmos
    key-encoding: secp256k1
    gas-prices: "0.01uatom"
  chain-2:
    id: osmosis-1
    rpc_addr: http://osmosis-rpc.example.com:26657
    grpc_addr: http://osmosis-grpc.example.com:9090
    account-prefix: osmo
    key-encoding: secp256k1
    gas-prices: "0.025uosmo"

Ensure your RPC endpoints are accessible and responding to queries. If you are running your own nodes, use localhost. If you are using public endpoints, verify they allow CORS headers if your relayer runs in a browser or requires specific headers. For production setups, always use HTTPS for RPC connections to prevent man-in-the-middle attacks.

Once the file is saved, validate the configuration by running a test command. This step checks if the relayer can reach the nodes and parse the chain IDs correctly. If the test fails, check your network connectivity and ensure the chain_id matches the actual genesis hash of the target chain.

Cosmos IBC

Run the channel handshake

Cross-chain communication in the Cosmos ecosystem relies on a strict two-phase handshake. First, you establish a connection between two chains. Second, you create a channel on top of that connection to handle actual data or token transfers. This process ensures both chains agree on the trust model before any packets are exchanged.

Start by initializing the connection. This step registers the counterparty chain on your local node. Run the following command, replacing the placeholder values with your specific chain identifiers and client IDs.

Shell
cosmoshub tx ibc core connection handshake-init \
  connection-0 \
  07-tendermint-0 \
  --from validator \
  --chain-id cosmoshub-4 \
  --node https://rpc.cosmos.network:443

Once the connection is open, you must create the channel. This defines the specific path for your application data. Use the channel handshake-init command, specifying the connection ID established in the previous step.

Shell
cosmoshub tx ibc core channel handshake-init \
  channel-0 \
  connection-0 \
  port-0 \
  --from validator \
  --chain-id cosmoshub-4 \
  --node https://rpc.cosmos.network:443

The final phase is the handshake completion. Both chains must acknowledge the channel state. Execute the channel handshake-ack command on the counterparty chain to finalize the setup. Verify the channel status using query ibc channel to ensure both sides are in the OPEN state.

Shell
cosmoshub tx ibc core channel handshake-ack \
  channel-0 \
  connection-0 \
  port-0 \
  --from validator \
  --chain-id cosmoshub-4 \
  --node https://rpc.cosmos.network:443

With the channel open, you can now send packets. Use the send-tx command to transfer tokens or IBC packets across the newly established link. Monitor the transaction status to confirm successful delivery.

Shell
cosmoshub tx ibc-transfer transfer transfer channel-0 cosmos1... 100uatom --from validator

Test the token transfer

With the channel established, the final verification step is to execute a live IBC transfer. This confirms that the relayers are correctly forwarding packets and that the IBC middleware is functioning between the source and destination chains.

Cosmos IBC
1
Initiate the transfer

Use the Cosmos CLI or a compatible wallet interface to send a small test amount of tokens (e.g., 1 ATOM) from the source chain to the destination address on the new chain. Ensure you specify the correct channel ID identified in the previous step. This action generates an IBC packet that will be relayed across the network.

Cosmos IBC
2
Monitor the relayer

Watch the relayer logs or the block explorer for the source chain. You should see the packet emission, followed by the relayer picking up the packet and submitting the proof on the destination chain. This process typically takes a few seconds to a minute depending on the relayer's update frequency.

Cosmos IBC
3
Verify receipt on destination

Check the destination chain's block explorer or wallet for the incoming tokens. The balance should reflect the transferred amount plus any network fees. If the tokens do not appear within a reasonable timeframe (e.g., 5 minutes), check the relayer status for errors or packet timeouts.

If the transfer succeeds, your cross-chain communication setup is operational. If it fails, review the channel connection status and ensure the relayer is active for both chains. For a visual walkthrough of this process, see the demo below.

Check relayer logs for errors

Relayers act as the nervous system for IBC-Go, translating state proofs between chains. When a handshake fails or packets drop, the relayer logs are your primary diagnostic tool. You need to parse these logs to identify whether the failure stems from connection timeouts, missing client updates, or malformed packet acknowledgments.

Start by running the relayer in verbose mode to capture full transaction hashes and error codes. Look specifically for packet_ack failures, which indicate that the receiving chain rejected the packet. Common causes include insufficient gas limits on the destination chain or a mismatched timeout height. If you see repeated client not found errors, the light client on the source chain may be out of sync, requiring a manual client update.

For packet loss, check if the relayer is hitting rate limits on either chain. Cosmos chains enforce strict RPC rate limits; exceeding them results in dropped packets. Increase your relayer's polling interval or switch to a dedicated RPC endpoint to mitigate this. Additionally, verify that the channel version strings match exactly between the two chains. Even a minor version mismatch in the IBC application layer will cause silent packet drops without explicit transaction errors.

Verify the final state

With the channel handshake complete, you must confirm that the IBC connection is active and that assets have successfully traversed the path. This verification step ensures that the light clients on both chains are synchronized and that the escrow accounts are correctly tracking the transfer.

Run the query command on the source chain to check the channel status. A state of STATE_OPEN confirms the channel is ready for transfers. If the state is STATE_INIT or STATE_TRYOPEN, the handshake is still in progress and you must wait for completion.

Cosmos IBC
1
Check channel status on Chain A

Execute gaiq query ibc channel connections <connection-handle> -o json to retrieve the current state. Ensure the output returns STATE_OPEN.

Cosmos IBC in
2
Verify balance on Chain B

Run gaiq query bank balances <wallet-address> on the destination chain. Confirm that the transferred tokens appear in the recipient's account.

Cosmos IBC in
3
Confirm escrow on Chain A

Check the escrow account associated with the channel port. The balance should reflect the amount locked for the transfer, ensuring no funds are lost or stuck.

The following image illustrates the successful completion of an IBC transfer, showing the token movement between Cosmos ecosystem chains.

Cosmos IBC

Once you see the funds in the destination wallet and the channel remains open, the cross-chain communication is verified. You can now proceed with confidence, knowing the bridge is functional and the packets are being relayed correctly by the relayer nodes.

Common ibc: what to check next