diff --git a/res/ui/community_view.ui b/res/ui/community_view.ui
deleted file mode 100644
index 8827fe266a1f83882dcac7b74cab8c299502e0db..0000000000000000000000000000000000000000
--- a/res/ui/community_view.ui
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>CommunityWidget</class>
- <widget class="QWidget" name="CommunityWidget">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>624</width>
-    <height>429</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>Form</string>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <widget class="QTabWidget" name="tabs"/>
-   </item>
-  </layout>
- </widget>
- <resources>
-  <include location="../icons/icons.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/src/sakia/gui/certification/controller.py b/src/sakia/gui/certification/controller.py
index 4d9171a1ede6807adc694ef5970efc8185a13bf4..94aef99deaa17eff8054ff14acc8af2e23569e4a 100644
--- a/src/sakia/gui/certification/controller.py
+++ b/src/sakia/gui/certification/controller.py
@@ -128,11 +128,12 @@ class CertificationController(ComponentController):
         """
         Validate the dialog
         """
+        self.view.button_box.setDisabled(True)
         pubkey = self.selected_pubkey()
         if pubkey:
             password = await self.password_asker.async_exec()
             if password == "":
-                self.view.enable_button_box()
+                self.view.button_box.setEnabled(True)
                 return
             QApplication.setOverrideCursor(Qt.WaitCursor)
             result = await self.account.certify(password, self.community, pubkey)
@@ -143,7 +144,7 @@ class CertificationController(ComponentController):
             else:
                 await self.view.show_error(result[1])
                 QApplication.restoreOverrideCursor()
-                self.view.enable_button_box()
+                self.view.button_box.setEnabled(True)
 
     def reject(self):
         self.view.reject()
@@ -200,7 +201,7 @@ class CertificationController(ComponentController):
     def change_current_community(self, index):
         self.model.change_community(index)
         self.search_user.set_community(self.community)
-        self.member_widget.change_community(self.community)
+        self.user_information.change_community(self.community)
         self.refresh()
 
     def async_exec(self):
diff --git a/src/sakia/gui/main_window/controller.py b/src/sakia/gui/main_window/controller.py
index bdde74da84c7f5465b4b5d65acabff7349e1ddfa..b29a7b238683bb2ba4d9c4319ef38fcdb90415e5 100644
--- a/src/sakia/gui/main_window/controller.py
+++ b/src/sakia/gui/main_window/controller.py
@@ -64,7 +64,7 @@ class MainWindowController(ComponentController):
         main_window.navigation = main_window.attach(NavigationController.create(main_window, app))
         view.bottom_layout.insertWidget(0, main_window.navigation._view)
         main_window.navigation.community_changed.connect(main_window.handle_community_change)
-        main_window.navigation.account_changed.connect(main_window.handle_community_change)
+        main_window.navigation.account_changed.connect(main_window.handle_account_change)
 
         main_window.toolbar = main_window.attach(ToolbarController.create(main_window, app,
                                                                           app.current_account, None,
@@ -116,14 +116,15 @@ class MainWindowController(ComponentController):
         Set current account
         :param sakia.core.Account account:
         """
-        self.toolbar.set_account(account)
+        self.toolbar.account = account
+        self.password_asker.change_account(account)
 
     def handle_community_change(self, community):
         """
         Set current community
         :param sakia.core.Community community:
         """
-        self.toolbar.set_community(community)
+        self.toolbar.community = community
 
     def refresh(self):
         """
diff --git a/src/sakia/gui/navigation/navigation.ui b/src/sakia/gui/navigation/navigation.ui
index 0da57f788436ddbfe80153f08eda624ea2ad030f..266315e5655d3fb9fd7c34bf21de42db92fa99ce 100644
--- a/src/sakia/gui/navigation/navigation.ui
+++ b/src/sakia/gui/navigation/navigation.ui
@@ -28,6 +28,18 @@
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
+     <property name="editTriggers">
+      <set>QAbstractItemView::NoEditTriggers</set>
+     </property>
+     <property name="showDropIndicator" stdset="0">
+      <bool>false</bool>
+     </property>
+     <property name="itemsExpandable">
+      <bool>true</bool>
+     </property>
+     <property name="headerHidden">
+      <bool>true</bool>
+     </property>
     </widget>
    </item>
    <item>
diff --git a/src/sakia/gui/navigation/view.py b/src/sakia/gui/navigation/view.py
index 4518017f0b25ef779e55641a3b9d3b2762b6fe1a..a822e992c19fb117bda9e10bbf926fa602fcd5ab 100644
--- a/src/sakia/gui/navigation/view.py
+++ b/src/sakia/gui/navigation/view.py
@@ -21,6 +21,7 @@ class NavigationView(QFrame, Ui_Navigation):
         :param sakia.gui.navigation.model.NavigationModel
         """
         self.tree_view.setModel(model.generic_tree())
+        self.tree_view.expandAll()
 
     def add_widget(self, widget):
         """
diff --git a/src/sakia/gui/toolbar/controller.py b/src/sakia/gui/toolbar/controller.py
index b9622b26b719ce238c9ebeba69fcbf0c6462dd5a..c44950b0eb22253f7aa37055ef4e141112f1eecb 100644
--- a/src/sakia/gui/toolbar/controller.py
+++ b/src/sakia/gui/toolbar/controller.py
@@ -7,6 +7,7 @@ from ...tools.decorators import asyncify, once_at_a_time, cancel_once_task
 from ..widgets.dialogs import QAsyncMessageBox, QAsyncFileDialog, dialog_async_exec
 from ..widgets import toast
 from ..certification.controller import CertificationController
+from ..transfer.controller import TransferController
 import logging
 
 
@@ -199,13 +200,10 @@ The process to join back the community later will have to be done again.""")
                                      self.account)
 
     def open_transfer_money_dialog(self):
-        dialog = TransferMoneyDialog(self.app,
-                                     self.account,
-                                     self.password_asker,
-                                     self.community_view.community,
-                                     None)
-        if dialog.exec() == QDialog.Accepted:
-            self.community_view.tab_history.table_history.model().sourceModel().refresh_transfers()
+        dialog = TransferController.open_dialog(self, self.model.app,
+                                                account=self.model.account,
+                                                password_asker=self.password_asker,
+                                                community=self.model.community)
 
     def retranslateUi(self, widget):
         """
diff --git a/src/sakia/gui/transfer/__init__.py b/src/sakia/gui/transfer/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/sakia/gui/transfer/controller.py b/src/sakia/gui/transfer/controller.py
new file mode 100644
index 0000000000000000000000000000000000000000..33fc5660058f454e2589ce4315b58f642c026c65
--- /dev/null
+++ b/src/sakia/gui/transfer/controller.py
@@ -0,0 +1,247 @@
+from ..component.controller import ComponentController
+from ..search_user.controller import SearchUserController
+from ..user_information.controller import UserInformationController
+from .view import TransferView
+from .model import TransferModel
+from sakia.tools.decorators import asyncify
+from PyQt5.QtWidgets import QApplication
+from PyQt5.QtCore import Qt
+import logging
+import asyncio
+
+
+class TransferController(ComponentController):
+    """
+    The transfer component controller
+    """
+
+    def __init__(self, parent, view, model, search_user, user_information, password_asker):
+        """
+        Constructor of the transfer component
+
+        :param sakia.gui.transfer.view.TransferView: the view
+        :param sakia.gui.transfer.model.TransferModel model: the model
+        """
+        super().__init__(parent, view, model)
+        self.password_asker = password_asker
+        self.search_user = search_user
+        self.user_information = user_information
+        self.view.button_box.accepted.connect(self.accept)
+        self.view.button_box.rejected.connect(self.reject)
+        self.view.combo_community.currentIndexChanged.connect(self.change_current_community)
+        self.view.combo_wallets.currentIndexChanged.connect(self.change_current_wallet)
+        self.view.spinbox_amount.valueChanged.connect(self.handle_amount_change)
+        self.view.spinbox_relative.valueChanged.connect(self.handle_relative_change)
+
+    @classmethod
+    def create(cls, parent, app, **kwargs):
+        """
+        Instanciate a transfer component
+        :param sakia.gui.component.controller.ComponentController parent:
+        :param sakia.core.Application app:
+        :return: a new Transfer controller
+        :rtype: TransferController
+        """
+        account = kwargs['account']
+        community = kwargs['community']
+        transfer = kwargs['transfer']
+        password_asker = kwargs['password_asker']
+        communities_names = [c.name for c in account.communities]
+        wallets_names = [w.name for w in account.wallets]
+        contacts_names = [c['name'] for c in account.contacts]
+
+        view = TransferView(parent.view, None, None, communities_names, contacts_names, wallets_names)
+        model = TransferModel(None, app, account=account, community=community, resent_transfer=transfer)
+        transfer = cls(parent, view, model, None, None, password_asker)
+
+        search_user = SearchUserController.create(transfer, app,
+                                                  account=model.account,
+                                                  community=model.community)
+        transfer.set_search_user(search_user)
+
+        user_information = UserInformationController.create(transfer, app,
+                                                            account=model.account,
+                                                            community=model.community,
+                                                            identity=None)
+        transfer.set_user_information(user_information)
+        model.setParent(transfer)
+        return transfer
+
+    @classmethod
+    def open_dialog(cls, parent, app, account, password_asker, community):
+        dialog = cls.create(parent, app,
+                     account=account,
+                     password_asker=password_asker,
+                     community=community,
+                     transfer=None)
+        return dialog.exec()
+
+    @classmethod
+    async def send_money_to_identity(cls, parent, app, account, password_asker, community, identity):
+        dialog = cls.create(parent, app,
+                     account=account,
+                     password_asker=password_asker,
+                     community=community,
+                     transfer=None)
+        dialog.view.edit_pubkey.setText(identity.pubkey)
+        dialog.view.radio_pubkey.setChecked(True)
+        return await dialog.async_exec()
+
+    @classmethod
+    async def send_transfer_again(cls, parent, app, account, password_asker, community, resent_transfer):
+        dialog = cls.create(parent, app,
+                            account=account,
+                            password_asker=password_asker,
+                            community=community,
+                            resent_transfer=resent_transfer)
+        relative = await dialog.model.quant_to_rel(resent_transfer.metadata['amount'])
+        dialog.view.set_spinboxes_parameters(1, resent_transfer.metadata['amount'], relative)
+        dialog.view.change_relative_amount(relative)
+        dialog.view.change_quantitative_amount(resent_transfer.metadata['amount'])
+
+        account = resent_transfer.metadata['issuer']
+        wallet_index = [w.pubkey for w in app.current_account.wallets].index(account)
+        dialog.view.combo_wallets.setCurrentIndex(wallet_index)
+        dialog.view.edit_pubkey.setText(resent_transfer.metadata['receiver'])
+        dialog.view.radio_pubkey.setChecked(True)
+        dialog.view.edit_message.setText(resent_transfer.metadata['comment'])
+
+        return await dialog.async_exec()
+
+    @property
+    def view(self) -> TransferView:
+        return self._view
+
+    @property
+    def model(self) -> TransferModel:
+        return self._model
+
+    def set_search_user(self, search_user):
+        """
+
+        :param search_user:
+        :return:
+        """
+        self.search_user = search_user
+        self.view.set_search_user(search_user.view)
+        search_user.identity_selected.connect(self.refresh_user_information)
+
+    def set_user_information(self, user_information):
+        """
+
+        :param user_information:
+        :return:
+        """
+        self.user_information = user_information
+        self.view.set_user_information(user_information.view)
+
+    def refresh_user_information(self):
+        """
+        Refresh user information
+        """
+        pubkey = self.selected_pubkey()
+        self.user_information.search_identity(pubkey)
+
+    def selected_pubkey(self):
+        """
+        Get selected pubkey in the widgets of the window
+        :return: the current pubkey
+        :rtype: str
+        """
+        pubkey = None
+
+        if self.view.recipient_mode() == TransferView.RecipientMode.CONTACT:
+            contact_name = self.view.selected_contact()
+            pubkey = self.model.contact_name_pubkey(contact_name)
+        elif self.view.recipient_mode() == TransferView.RecipientMode.SEARCH:
+            if self.search_user.current_identity():
+                pubkey = self.search_user.current_identity().pubkey
+        else:
+            pubkey = self.view.pubkey_value()
+        return pubkey
+
+    @asyncify
+    async def accept(self):
+        logging.debug("Accept transfer action...")
+        self.view.button_box.setEnabled(False)
+        comment = self.view.edit_message.text()
+
+        logging.debug("checking recipient mode...")
+        recipient = self.selected_pubkey()
+        amount = self.view.spinbox_amount.value()
+
+        logging.debug("Showing password dialog...")
+        password = await self.password_asker.async_exec()
+        if password == "":
+            self.view.button_box.setEnabled(True)
+            return
+
+        logging.debug("Setting cursor...")
+        QApplication.setOverrideCursor(Qt.WaitCursor)
+
+        logging.debug("Send money...")
+        result = await self.model.send_money(recipient, amount, comment, password)
+        if result[0]:
+            await self.view.show_success(self.model.app.preferences['notifications'], recipient)
+            logging.debug("Restore cursor...")
+            QApplication.restoreOverrideCursor()
+
+            # If we sent back a transaction we cancel the first one
+            self.model.cancel_previous()
+            self.model.app.refresh_transfers.emit()
+            self.view.accept()
+        else:
+            await self.view.show_error(self.model.app.preferences['notifications'], result[1])
+
+            QApplication.restoreOverrideCursor()
+            self.view.button_box.setEnabled(True)
+
+    def reject(self):
+        self.view.reject()
+
+    @asyncify
+    async def refresh(self):
+        amount = await self.model.wallet_value()
+        total_text = await self.model.localized_amount(amount)
+        self.view.refresh_labels(total_text, self.model.community.currency)
+
+        if amount == 0:
+            self.view.set_button_box(TransferView.ButtonBoxState.NO_AMOUNT)
+        else:
+            self.view.set_button_box(TransferView.ButtonBoxState.OK)
+
+        max_relative = await self.model.quant_to_rel(amount)
+        current_base = await self.model.current_base()
+
+        self.view.set_spinboxes_parameters(pow(10, current_base), amount, max_relative)
+
+    @asyncify
+    async def handle_amount_change(self, value):
+        relative = await self.model.quant_to_rel(value)
+        self.view.change_relative_amount(relative)
+
+    @asyncify
+    async def handle_relative_change(self, value):
+        amount = await self.model.rel_to_quant(value)
+        self.view.change_quantitative_amount(amount)
+
+    def change_current_community(self, index):
+        self.model.change_community(index)
+        self.search_user.set_community(self.community)
+        self.user_information.change_community(self.community)
+        self.refresh()
+
+    def change_current_wallet(self, index):
+        self.model.change_wallet(index)
+        self.refresh()
+
+    def async_exec(self):
+        future = asyncio.Future()
+        self.view.finished.connect(lambda r: future.set_result(r))
+        self.view.open()
+        self.refresh()
+        return future
+
+    def exec(self):
+        self.refresh()
+        self.view.exec()
\ No newline at end of file
diff --git a/src/sakia/gui/transfer/model.py b/src/sakia/gui/transfer/model.py
new file mode 100644
index 0000000000000000000000000000000000000000..10d306a21015c4a9b177a2f38e9719b4d7c20a90
--- /dev/null
+++ b/src/sakia/gui/transfer/model.py
@@ -0,0 +1,118 @@
+from sakia.gui.component.model import ComponentModel
+
+
+class TransferModel(ComponentModel):
+    """
+    The model of transfer component
+    """
+
+    def __init__(self, parent, app, account, community, resent_transfer):
+        super().__init__(parent)
+        self.app = app
+        self.account = account
+        self.resent_transfer = resent_transfer
+        self.community = community if community else self.account.communities[0]
+        self.wallet = self.account.wallets[0]
+
+    def contact_name_pubkey(self, name):
+        """
+        Get the pubkey of a contact from its name
+        :param str name:
+        :return:
+        :rtype: str
+        """
+        for contact in self.account.contacts:
+            if contact['name'] == name:
+                return contact['pubkey']
+
+    async def rel_to_quant(self, rel_value):
+        """
+        Get the quantitative value of a relative amount
+        :param float rel_value:
+        :rtype: int
+        """
+        ud_block = await self.community.get_ud_block()
+        if ud_block:
+            dividend = ud_block['dividend']
+            base = ud_block['unitbase']
+        else:
+            dividend = 1
+            base = 0
+        amount = rel_value * dividend * pow(10, base)
+        # amount is rounded to the nearest power of 10 depending of last ud base
+        rounded = int(pow(10, base) * round(float(amount) / pow(10, base)))
+        return rounded
+
+    async def quant_to_rel(self, amount):
+        """
+        Get the relative value of a given amount
+        :param int amount:
+        :rtype: float
+        """
+
+        ud_block = await self.community.get_ud_block()
+        if ud_block:
+            dividend = ud_block['dividend']
+            base = ud_block['unitbase']
+        else:
+            dividend = 1
+            base = 0
+        relative = amount / (dividend * pow(10, base))
+        return relative
+
+    async def wallet_value(self):
+        """
+        Get the value of the current wallet in the current community
+        """
+        return await self.wallet.value(self.community)
+
+    async def current_base(self):
+        """
+        Get the current base of the network
+        """
+        ud_block = await self.community.get_ud_block()
+        if ud_block:
+            base = ud_block['unitbase']
+        else:
+            base = 0
+        return base
+
+    async def localized_amount(self, amount):
+        """
+        Get the value of the current referential
+        """
+        localized = await self.account.current_ref.instance(amount, self.community, self.app) \
+            .diff_localized(units=True,
+                            international_system=self.app.preferences['international_system_of_units'])
+        return localized
+
+    def change_community(self, index):
+        """
+        Change the current community
+        :param int index: index in the list of communities
+        """
+        self.community = self.account.communities[index]
+
+    def change_wallet(self, index):
+        """
+        Change the current wallet
+        :param int index: index in the list of wallets
+        """
+        self.wallet = self.account.wallets[index]
+
+    def cancel_previous(self):
+        if self.resent_transfer:
+            self.resent_transfer.cancel()
+
+    async def send_money(self, recipient, amount, comment, password):
+        """
+        Send money to given recipient using the account
+        :param str recipient:
+        :param int amount:
+        :param str comment:
+        :param str password:
+        :return: the result of the send
+        """
+
+        return await self.wallet.send_money(self.account.salt, password, self.community,
+                                   recipient, amount, comment)
\ No newline at end of file
diff --git a/src/sakia/gui/transfer.py b/src/sakia/gui/transfer/transfer.py
similarity index 96%
rename from src/sakia/gui/transfer.py
rename to src/sakia/gui/transfer/transfer.py
index 90a07f08822ad102b97e95a926fec53a4ff90df8..39bf940c96bd457aa54341b5ce62ba288486c92c 100644
--- a/src/sakia/gui/transfer.py
+++ b/src/sakia/gui/transfer/transfer.py
@@ -195,15 +195,6 @@ class TransferMoneyDialog(QObject):
 
     @asyncify
     async def relative_amount_changed(self, value):
-        ud_block = await self.community.get_ud_block()
-        if ud_block:
-            dividend = ud_block['dividend']
-            base = ud_block['unitbase']
-        else:
-            dividend = 1
-            base = 0
-        amount = value * dividend * pow(10, base)
-        amount = int(pow(10, base) * round(float(amount) / pow(10, base)))
         self.ui.spinbox_amount.blockSignals(True)
         self.ui.spinbox_amount.setValue(amount)
         self.ui.spinbox_amount.blockSignals(False)
diff --git a/res/ui/transfer.ui b/src/sakia/gui/transfer/transfer.ui
similarity index 50%
rename from res/ui/transfer.ui
rename to src/sakia/gui/transfer/transfer.ui
index 018f7f3e4603839da12d1cb2a103ae7d7dc18c6c..5c5f691f6201e36bfc52596690c3e0f833e700c1 100644
--- a/res/ui/transfer.ui
+++ b/src/sakia/gui/transfer/transfer.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>496</width>
-    <height>485</height>
+    <width>800</width>
+    <height>500</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -27,151 +27,161 @@
     </widget>
    </item>
    <item>
-    <widget class="QGroupBox" name="groupBox">
+    <widget class="QGroupBox" name="group_box_recipient">
      <property name="title">
       <string>Transfer money to</string>
      </property>
-     <layout class="QVBoxLayout" name="verticalLayout_2">
+     <layout class="QHBoxLayout" name="horizontalLayout_5">
       <item>
-       <layout class="QHBoxLayout" name="horizontalLayout_2">
-        <item>
-         <widget class="QRadioButton" name="radio_contact">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="text">
-           <string>Con&amp;tact</string>
-          </property>
-          <property name="checked">
-           <bool>true</bool>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <spacer name="horizontalSpacer_3">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeType">
-           <enum>QSizePolicy::Maximum</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-        <item>
-         <widget class="QComboBox" name="combo_contact">
-          <property name="enabled">
-           <bool>true</bool>
-          </property>
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item>
-       <layout class="QHBoxLayout" name="horizontalLayout">
-        <item>
-         <widget class="QRadioButton" name="radio_pubkey">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="text">
-           <string>&amp;Recipient public key</string>
-          </property>
-          <property name="checked">
-           <bool>false</bool>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <spacer name="horizontalSpacer_2">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeType">
-           <enum>QSizePolicy::Maximum</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-        <item>
-         <widget class="QLineEdit" name="edit_pubkey">
-          <property name="enabled">
-           <bool>false</bool>
-          </property>
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="inputMask">
-           <string/>
-          </property>
-          <property name="text">
-           <string/>
-          </property>
-          <property name="placeholderText">
-           <string>Key</string>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item>
-       <layout class="QHBoxLayout" name="horizontalLayout_5">
+       <layout class="QVBoxLayout" name="verticalLayout_4">
         <property name="topMargin">
          <number>6</number>
         </property>
+        <property name="bottomMargin">
+         <number>6</number>
+        </property>
         <item>
-         <widget class="QRadioButton" name="radio_search">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="text">
-           <string>Search &amp;user</string>
-          </property>
-         </widget>
+         <layout class="QHBoxLayout" name="horizontalLayout_2">
+          <item>
+           <widget class="QRadioButton" name="radio_contact">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>Con&amp;tact</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer_3">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeType">
+             <enum>QSizePolicy::Maximum</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QComboBox" name="combo_contact">
+            <property name="enabled">
+             <bool>true</bool>
+            </property>
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+           </widget>
+          </item>
+         </layout>
         </item>
         <item>
-         <spacer name="horizontalSpacer">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeType">
-           <enum>QSizePolicy::Maximum</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
+         <layout class="QHBoxLayout" name="horizontalLayout">
+          <item>
+           <widget class="QRadioButton" name="radio_pubkey">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>&amp;Recipient public key</string>
+            </property>
+            <property name="checked">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer_2">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeType">
+             <enum>QSizePolicy::Maximum</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="edit_pubkey">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="inputMask">
+             <string/>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="placeholderText">
+             <string>Key</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="layout_search_user">
+          <property name="topMargin">
+           <number>6</number>
           </property>
-         </spacer>
+          <item>
+           <widget class="QRadioButton" name="radio_search">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>Search &amp;user</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeType">
+             <enum>QSizePolicy::Maximum</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
         </item>
        </layout>
       </item>
diff --git a/src/sakia/gui/transfer/view.py b/src/sakia/gui/transfer/view.py
new file mode 100644
index 0000000000000000000000000000000000000000..327731a1d53803d99cbb615f7967bcc1c8893db2
--- /dev/null
+++ b/src/sakia/gui/transfer/view.py
@@ -0,0 +1,164 @@
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox
+from PyQt5.QtGui import QRegExpValidator
+from PyQt5.QtCore import QT_TRANSLATE_NOOP, QRegExp
+from .transfer_uic import Ui_TransferMoneyDialog
+from enum import Enum
+from ..widgets import toast
+from ..widgets.dialogs import QAsyncMessageBox
+
+
+class TransferView(QDialog, Ui_TransferMoneyDialog):
+    """
+    Transfer component view
+    """
+
+    class ButtonBoxState(Enum):
+        NO_AMOUNT = 0
+        OK = 1
+
+    class RecipientMode(Enum):
+        CONTACT = 0
+        PUBKEY = 1
+        SEARCH = 2
+
+    _button_box_values = {
+        ButtonBoxState.NO_AMOUNT: (False,
+                                   QT_TRANSLATE_NOOP("TransferView", "No amount. Please give the transfer amount")),
+        ButtonBoxState.OK: (True, QT_TRANSLATE_NOOP("CertificationView", "&Ok"))
+    }
+
+    def __init__(self, parent, search_user_view, user_information_view,
+                 communities_names, contacts_names, wallets_names):
+        """
+
+        :param parent:
+        :param sakia.gui.search_user.view.SearchUserView search_user_view:
+        :param sakia.gui.user_information.view.UserInformationView user_information_view:
+        :param list[str] communities_names:
+        :param list[str] contacts_names:
+        :param list[str] wallets_names:
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        self.radio_contact.toggled.connect(lambda c, radio=TransferView.RecipientMode.CONTACT: self.recipient_mode_changed(radio))
+        self.radio_pubkey.toggled.connect(lambda c, radio=TransferView.RecipientMode.PUBKEY: self.recipient_mode_changed(radio))
+        self.radio_search.toggled.connect(lambda c, radio=TransferView.RecipientMode.SEARCH: self.recipient_mode_changed(radio))
+
+        regexp = QRegExp('^([ a-zA-Z0-9-_:/;*?\[\]\(\)\\\?!^+=@&~#{}|<>%.]{0,255})$')
+        validator = QRegExpValidator(regexp)
+        self.edit_message.setValidator(validator)
+
+        for name in communities_names:
+            self.combo_community.addItem(name)
+
+        for name in sorted(contacts_names):
+            self.combo_contact.addItem(name)
+
+        for name in wallets_names:
+            self.combo_wallets.addItem(name)
+
+        if len(contacts_names) == 0:
+            self.combo_contact.setEnabled(False)
+            self.radio_pubkey.setChecked(True)
+            self.radio_contact.setEnabled(False)
+
+        self.search_user = search_user_view
+        self.user_information_view = user_information_view
+
+    def recipient_mode(self):
+        if self.radio_contact.isChecked():
+            return TransferView.RecipientMode.CONTACT
+        elif self.radio_search.isChecked():
+            return TransferView.RecipientMode.SEARCH
+        else:
+            return TransferView.RecipientMode.PUBKEY
+
+    def selected_contact(self):
+        return self.combo_contact.currentText()
+
+    def set_search_user(self, search_user_view):
+        """
+
+        :param sakia.gui.search_user.view.SearchUserView search_user_view:
+        :return:
+        """
+        self.search_user = search_user_view
+        self.layout_search_user.addWidget(search_user_view)
+        self.search_user.button_reset.hide()
+
+    def set_user_information(self, user_information_view):
+        self.user_information_view = user_information_view
+        self.group_box_recipient.layout().addWidget(user_information_view)
+
+    def recipient_mode_changed(self, radio):
+        """
+        :param str radio:
+        """
+        self.edit_pubkey.setEnabled(radio == TransferView.RecipientMode.PUBKEY)
+        self.combo_contact.setEnabled(radio == TransferView.RecipientMode.CONTACT)
+        self.search_user.setEnabled(radio == TransferView.RecipientMode.SEARCH)
+
+    def change_quantitative_amount(self, amount):
+        """
+        Change relative amount with signals blocked
+        :param amount:
+        """
+        self.spinbox_amount.blockSignals(True)
+        self.spinbox_amount.setValue(amount)
+        self.spinbox_amount.blockSignals(False)
+
+    def change_relative_amount(self, relative):
+        """
+        Change the quantitative amount with signals blocks
+        :param relative:
+        """
+        self.spinbox_relative.blockSignals(True)
+        self.spinbox_relative.setValue(relative)
+        self.spinbox_relative.blockSignals(False)
+
+    def set_spinboxes_parameters(self, tick_quant, max_quant, max_rel):
+        """
+        Configure the spinboxes
+        It should depend on what the last UD base is
+        :param int tick_quant:
+        :param int max_quant:
+        :param float max_rel:
+        """
+        self.spinbox_amount.setMaximum(max_quant)
+        self.spinbox_relative.setMaximum(max_rel)
+        self.spinbox_amount.setSingleStep(tick_quant)
+
+    def refresh_labels(self, total_text, currency):
+        """
+        Refresh displayed texts
+        :param str total_text:
+        :param str currency:
+        """
+        self.label_total.setText("{0}".format(total_text))
+        self.spinbox_amount.setSuffix(" " + currency)
+
+    def set_button_box(self, state, **kwargs):
+        """
+        Set button box state
+        :param sakia.gui.transfer.view.TransferView.ButtonBoxState state: the state of te button box
+        :param dict kwargs: the values to replace from the text in the state
+        :return:
+        """
+        button_box_state = TransferView._button_box_values[state]
+        self.button_box.button(QDialogButtonBox.Ok).setEnabled(button_box_state[0])
+        self.button_box.button(QDialogButtonBox.Ok).setText(button_box_state[1].format(**kwargs))
+
+    async def show_success(self, notification, recipient):
+        if notification:
+            toast.display(self.tr("Transfer"),
+                      self.tr("Success sending money to {0}").format(recipient))
+        else:
+            await QAsyncMessageBox.information(self.widget, self.tr("Transfer"),
+                      self.tr("Success sending money to {0}").format(recipient))
+
+    async def show_error(self, notification, error_txt):
+        if notification:
+            toast.display(self.tr("Transfer"), "Error : {0}".format(error_txt))
+        else:
+            await QAsyncMessageBox.critical(self.widget, self.tr("Transfer"), error_txt)
diff --git a/src/sakia/gui/widgets/context_menu.py b/src/sakia/gui/widgets/context_menu.py
index f2b668fb561f2abdf68ea893bb5d67ef51599e9f..fe34ff8db721241803a13ba2cc38adfbf2b3cfd4 100644
--- a/src/sakia/gui/widgets/context_menu.py
+++ b/src/sakia/gui/widgets/context_menu.py
@@ -5,7 +5,7 @@ import logging
 
 from ..user_information.controller import UserInformationController
 from ..contact import ConfigureContactDialog
-from ..transfer import TransferMoneyDialog
+from ..transfer.controller import TransferController
 from ..certification.controller import CertificationController
 from ...tools.decorators import asyncify
 from ...core.transfer import Transfer, TransferState
@@ -143,7 +143,7 @@ class ContextMenu(QObject):
 
     @asyncify
     async def send_money(self, identity):
-        await TransferMoneyDialog.send_money_to_identity(self._app, self._account, self._password_asker,
+        await TransferController.send_money_to_identity(None, self._app, self._account, self._password_asker,
                                                             self._community, identity)
         self._app.refresh_transfers.emit()
 
@@ -157,7 +157,7 @@ class ContextMenu(QObject):
 
     @asyncify
     async def send_again(self, transfer):
-        await TransferMoneyDialog.send_transfer_again(self._app, self._app.current_account,
+        await TransferController.send_transfer_again(None, self._app, self._app.current_account,
                                      self._password_asker, self._community, transfer)
         self._app.refresh_transfers.emit()