/ Authenticate owner
/ perform custom logic
    
/ Construct controller portID based on interchain account owner address
portID, err := icatypes.NewControllerPortID(owner.String())
    if err != nil {
    return err
}
    
/ Obtain data to be sent to the host chain. 
/ In this example, the owner of the interchain account would like to send a bank MsgSend to the host chain. 
/ The appropriate serialization function should be called. The host chain must be able to deserialize the transaction. 
/ If the host chain is using the ibc-go host module, `SerializeCosmosTx` should be used. 
    msg := &banktypes.MsgSend{
    FromAddress: fromAddr,
    ToAddress: toAddr,
    Amount: amt
}
data, err := icatypes.SerializeCosmosTx(keeper.cdc, []proto.Message{
    msg
})
    if err != nil {
    return err
}
/ Construct packet data
    packetData := icatypes.InterchainAccountPacketData{
    Type: icatypes.EXECUTE_TX,
    Data: data,
}
/ Obtain timeout timestamp
/ An appropriate timeout timestamp must be determined based on the usage of the interchain account.
/ If the packet times out, the channel will be closed requiring a new channel to be created.
    timeoutTimestamp := obtainTimeoutTimestamp()
/ Send the interchain accounts packet, returning the packet sequence
/ A nil channel capability can be passed, since the controller submodule (and not the authentication module) 
/ claims the channel capability since ibc-go v6.
seq, err = keeper.icaControllerKeeper.SendTx(ctx, nil, portID, packetData, timeoutTimestamp)