Synopsis
Learn how to implement IBC v2 applications To build an IBC v2 application the following steps are required:- Implement the
IBCModuleinterface - Bind Ports
- Implement the IBCModule Keeper
- Implement application payload and success acknowledgement
- Set and Seal the IBC Router
- No need to support channel handshake callbacks
- Flexibility on upgrading application versioning, no need to use channel upgradability to renegotiate an application version, simply support the application version on both sides of the connection.
- Flexibility to choose your desired encoding type.
Implement the IBCModule interface
The Cosmos SDK expects all IBC modules to implement the IBCModule
interface. This interface contains all of the callbacks IBC expects modules to implement. Note that for IBC v2, an application developer no longer needs to implement callbacks for the channel handshake. Note that this interface is distinct from the porttypes.IBCModule interface used for IBC Classic.
module.go file, add the following line:
Packet callbacks
IBC expects modules to implement callbacks for handling the packet lifecycle, as defined in theIBCModule interface.
With IBC v2, modules are not directly connected. Instead a pair of clients are connected and register the counterparty clientID. Packets are routed to the relevant application module by the portID registered in the Router. Relayers send packets between the routers/packet handlers on each chain.

- A user sends a message to the IBC packet handler
- The IBC packet handler validates the message, creates the packet and stores the commitment and returns the packet sequence number. The
Payload, which contains application specific data, is routed to the relevant application. - If the counterparty writes an acknowledgement of the packet then the sending chain will process the acknowledgement.
- If the packet is not successfully received before the timeout, then the sending chain processes the packet’s timeout.
Sending packets
MsgSendPacket is sent by a user to the channel v2 message server, which calls ChannelKeeperV2.SendPacket. This validates the message, creates the packet, stores the commitment and returns the packet sequence number. The application must specify its own payload which is used by the application and sent with MsgSendPacket.
An application developer needs to implement the custom logic the application executes when a packet is sent.
Receiving packets
To handle receiving packets, the module must implement theOnRecvPacket callback. An application module should validate and confirm support for the given version and encoding method used as there is greater flexibility in IBC v2 to support a range of versions and encoding methods.
The OnRecvPacket callback is invoked by the IBC module after the packet has been proven to be valid and correctly processed by the IBC
keepers.
Thus, the OnRecvPacket callback only needs to worry about making the appropriate state
changes given the packet data without worrying about whether the packet is valid or not.
Modules may return to the IBC handler an acknowledgement which implements the Acknowledgement interface.
The IBC handler will then commit this acknowledgement of the packet so that a relayer may relay the
acknowledgement back to the sender module.
The state changes that occurr during this callback could be:
- the packet processing was successful as indicated by the
PacketStatus_Successand anAcknowledgement()will be written - if the packet processing was unsuccessful as indicated by the
PacketStatus_Failureand anackErrwill be written
Acknowledging packets
After a module writes an acknowledgement, a relayer can relay back the acknowledgement to the sender module. The sender module can then process the acknowledgement using theOnAcknowledgementPacket callback. The contents of the
acknowledgement is entirely up to the application developer.
IBC will pass in the acknowledgements as []byte to this callback. The callback
is responsible for decoding the acknowledgement and processing it. The acknowledgement is serialised and deserialised using JSON.
Timeout packets
If the timeout for a packet is reached before the packet is successfully received or the receiving chain can no longer process the packet the sending chain must process the timeout usingOnTimeoutPacket. Again the IBC module will verify that the timeout is
valid, so our module only needs to implement the state machine logic for what to do once a
timeout is reached and the packet can no longer be received.
PacketDataUnmarshaler
ThePacketDataUnmarshaler interface is required for IBC v2 applications to implement because the encoding type is specified by the Payload and multiple encoding types are supported.
Bind Ports
Currently, ports must be bound on app initialization. In order to bind modules to their respective ports on initialization, the following needs to be implemented:Note thatAdd port ID to theportIDdoes not refer to a certain numerical ID, likelocalhost:8080with aportID8080. Rather it refers to the application module the port binds. For IBC Modules built with the Cosmos SDK, it defaults to the module’s name and for Cosmwasm contracts it defaults to the contract address.
GenesisState proto definition:
x/<moduleName>/types/genesis.go:
InitGenesis:
Implement the IBCModule Keeper
More information on implementing the IBCModule Keepers can be found in the keepers sectionPackets and Payloads
Applications developers need to define thePayload contained within an IBC packet. Note that in IBC v2 the timeoutHeight has been removed and only timeoutTimestamp is used. A packet can contain multiple payloads in a list. Each Payload includes:
RecvPacketResult. Note that if the packet processing fails, it is not possible to define a custom error acknowledgment, a constant ackErr is returned.