github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/27-interchain-accounts/controller/keeper/account.go (about) 1 package keeper 2 3 import ( 4 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 5 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 6 icatypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/27-interchain-accounts/types" 7 channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 8 host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 9 ) 10 11 // RegisterInterchainAccount is the entry point to registering an interchain account: 12 // - It generates a new port identifier using the provided owner string, binds to the port identifier and claims the associated capability. 13 // - Callers are expected to provide the appropriate application version string. 14 // - For example, this could be an ICS27 encoded metadata type or an ICS29 encoded metadata type with a nested application version. 15 // - A new MsgChannelOpenInit is routed through the MsgServiceRouter, executing the OnOpenChanInit callback stack as configured. 16 // - An error is returned if the port identifier is already in use. Gaining access to interchain accounts whose channels 17 // have closed cannot be done with this function. A regular MsgChannelOpenInit must be used. 18 func (k Keeper) RegisterInterchainAccount(ctx sdk.Context, connectionID, owner, version string) error { 19 portID, err := icatypes.NewControllerPortID(owner) 20 if err != nil { 21 return err 22 } 23 24 // if there is an active channel for this portID / connectionID return an error 25 activeChannelID, found := k.GetOpenActiveChannel(ctx, connectionID, portID) 26 if found { 27 return sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s on connection %s for owner %s", activeChannelID, portID, connectionID, owner) 28 } 29 30 switch { 31 case k.portKeeper.IsBound(ctx, portID) && !k.IsBound(ctx, portID): 32 return sdkerrors.Wrapf(icatypes.ErrPortAlreadyBound, "another module has claimed capability for and bound port with portID: %s", portID) 33 case !k.portKeeper.IsBound(ctx, portID): 34 cap := k.BindPort(ctx, portID) 35 if err := k.ClaimCapability(ctx, cap, host.PortPath(portID)); err != nil { 36 return sdkerrors.Wrapf(err, "unable to bind to newly generated portID: %s", portID) 37 } 38 } 39 40 msg := channeltypes.NewMsgChannelOpenInitV4(portID, version, channeltypes.ORDERED, []string{connectionID}, icatypes.PortID, icatypes.ModuleName) 41 handler := k.msgRouter.HandlerWithMsg(msg) 42 43 res, err := handler(ctx, msg) 44 if err != nil { 45 return err 46 } 47 48 // NOTE: The sdk msg handler creates a new EventManager, so events must be correctly propagated back to the current context 49 ctx.EventManager().EmitEvents(res.Events) 50 51 return nil 52 }