Learn how to integrate IBC to your application and send data packets to other chains.This document outlines the required steps to integrate and configure the IBC
module to your Cosmos SDK application and
send fungible token transfers to other chains.
The first step is to add the following modules to the BasicManager: x/capability, x/ibc,
and x/ibc-transfer. After that, we need to grant Minter and Burner permissions to
the ibc-transferModuleAccount to mint and burn relayed tokens.
/ app.gotype App struct { / baseapp, keys and subspaces definitions / other keepers / ... IBCKeeper *ibckeeper.Keeper / IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly TransferKeeper ibctransferkeeper.Keeper / for cross-chain fungible token transfers / make scoped keepers public for test purposes ScopedIBCKeeper capabilitykeeper.ScopedKeeper ScopedTransferKeeper capabilitykeeper.ScopedKeeper / ... / module and simulation manager definitions}
During initialization, besides initializing the IBC Keepers (for the x/ibc, and
x/ibc-transfer modules), we need to grant specific capabilities through the capability module
ScopedKeepers so that we can authenticate the object-capability permissions for each of the IBC
channels.
Copy
Ask AI
func NewApp(...args) *App { / define codecs and baseapp / add capability keeper and ScopeToModule for ibc module app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey]) / grant capabilities for the ibc and ibc-transfer modules scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName) scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName) / ... other modules keepers / Create IBC Keeper app.IBCKeeper = ibckeeper.NewKeeper( appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, ) / Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, ) transferModule := transfer.NewAppModule(app.TransferKeeper) / .. continues}
IBC needs to know which module is bound to which port so that it can route packets to the
appropriate module and call the appropriate callbacks. The port to module name mapping is handled by
IBC’s port Keeper. However, the mapping from module name to the relevant callbacks is accomplished
by the port
Router on the
IBC module.Adding the module routes allows the IBC handler to call the appropriate callback when processing a
channel handshake or a packet.Currently, a Router is static so it must be initialized and set correctly on app initialization.
Once the Router has been set, no new routes can be added.
Copy
Ask AI
/ app.gofunc NewApp(...args) *App { / .. continuation from above / Create static IBC router, add ibc-transfer module route, then set and seal it ibcRouter := port.NewRouter()ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) / Setting Router will finalize all routes by sealing router / No more routes can be added app.IBCKeeper.SetRouter(ibcRouter) / .. continues
One addition from IBC is the concept of HistoricalEntries which are stored on the staking module.
Each entry contains the historical information for the Header and ValidatorSet of this chain which is stored
at each height during the BeginBlock call. The historical info is required to introspect the
past historical info at any given height in order to verify the light client ConsensusState during the
connection handshake.The IBC module also has
BeginBlock logic as well. This is optional as it is only required if your application uses the localhost client to connect two different modules from the same chain.
Only register the ibc module to the SetOrderBeginBlockers if your
application will use the localhost (aka loopback) client.
Copy
Ask AI
/ app.gofunc NewApp(...args) *App { / .. continuation from above / add staking and ibc modules to BeginBlockers app.mm.SetOrderBeginBlockers( / other modules ... stakingtypes.ModuleName, ibchost.ModuleName, ) / ... / NOTE: Capability module must occur first so that it can initialize any capabilities / so that other modules that want to create or claim capabilities afterwards in InitChain / can do so safely. app.mm.SetOrderInitGenesis( capabilitytypes.ModuleName, / other modules ... ibchost.ModuleName, ibctransfertypes.ModuleName, ) / .. continues
IMPORTANT: The capability module must be declared first in
SetOrderInitGenesis
That’s it! You have now wired up the IBC module and are now able to send fungible tokens across
different chains. If you want to have a broader view of the changes take a look into the SDK’s
SimApp.