// Create Transfer Stack
// SendPacket, since it is originating from the application to core IBC:
// transferKeeper.SendPacket -> callbacks.SendPacket -> feeKeeper.SendPacket -> channel.SendPacket
// RecvPacket, message that originates from core IBC and goes down to app, the flow is the other way
// channel.RecvPacket -> fee.OnRecvPacket -> callbacks.OnRecvPacket -> transfer.OnRecvPacket
// transfer stack contains (from top to bottom):
// - IBC Packet Forward Middleware
// - IBC Callbacks Middleware
// - Transfer
// initialise the gas limit for callbacks, recommended to be 10M for use with cosmwasm contracts
maxCallbackGas := uint64(10_000_000)
// the keepers for the callbacks middleware
wasmStackIBCHandler := wasm.NewIBCHandler(app.WasmKeeper, app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper)
// create IBC module from bottom to top of stack
// Create Transfer Stack
var transferStack porttypes.IBCModule
transferStack = transfer.NewIBCModule(app.TransferKeeper)
// callbacks wraps the transfer stack as its base app, and uses PacketForwardKeeper as the ICS4Wrapper
// i.e. packet-forward-middleware is higher on the stack and sits between callbacks and the ibc channel keeper
// Since this is the lowest level middleware of the transfer stack, it should be the first entrypoint for transfer keeper's
// WriteAcknowledgement.
cbStack := ibccallbacks.NewIBCMiddleware(transferStack, app.PacketForwardKeeper, wasmStackIBCHandler, maxCallbackGas)
transferStack = packetforward.NewIBCMiddleware(
cbStack,
app.PacketForwardKeeper,
0,
packetforwardkeeper.DefaultForwardTransferPacketTimeoutTimestamp,
)
app.TransferKeeper.WithICS4Wrapper(cbStack)
// Create static IBC router, add app routes, then set and seal it
ibcRouter := porttypes.NewRouter()
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack)
ibcRouter.AddRoute(wasmtypes.ModuleName, wasmStackIBCHandler)
app.IBCKeeper.SetRouter(ibcRouter)