diff --git a/src/sakia/app.py b/src/sakia/app.py
index e7308cbe2b6624f285bc955b98419c62f3bd2a21..7af98fba55f72419200870120601fc63ac39c3bc 100644
--- a/src/sakia/app.py
+++ b/src/sakia/app.py
@@ -1,9 +1,4 @@
-"""
-Created on 1 févr. 2014
-
-@author: inso
-"""
-
+import attr
 import datetime
 import logging
 
@@ -15,7 +10,8 @@ from duniterpy.api.bma import API
 from . import __version__
 from .options import SakiaOptions
 from sakia.data.connectors import BmaConnector
-from sakia.services import NetworkService, BlockchainService, IdentitiesService, SourcesServices, TransactionsService
+from sakia.services import NetworkService, BlockchainService, IdentitiesService, \
+    SourcesServices, TransactionsService, DocumentsService
 from sakia.data.repositories import SakiaDatabase
 from sakia.data.processors import BlockchainProcessor, NodesProcessor, IdentitiesProcessor, \
     CertificationsProcessor, SourcesProcessor, TransactionsProcessor, ConnectionsProcessor
@@ -24,58 +20,59 @@ from sakia.decorators import asyncify
 from sakia.money import Relative
 
 
+@attr.s()
 class Application(QObject):
 
     """
     Managing core application datas :
     Accounts list and general configuration
     Saving and loading the application state
+
+
+    :param QCoreApplication qapp: Qt Application
+    :param quamash.QEventLoop loop: quamash.QEventLoop instance
+    :param sakia.options.SakiaOptions options: the options
+    :param sakia.data.entities.AppData app_data: the application data
+    :param sakia.data.entities.UserParameters parameters: the application current user parameters
+    :param sakia.data.repositories.SakiaDatabase db: The database
+    :param dict network_services: All network services for current currency
+    :param dict blockchain_services: All blockchain services for current currency
+    :param dict identities_services: All identities services for current currency
+    :param dict sources_services: All sources services for current currency
+    :param dict transactions_services: All transactions services for current currency
+    :param sakia.services.DocumentsService documents_service: A service to broadcast documents
     """
 
-    def __init__(self, qapp, loop, options, app_data, parameters, db,
-                 network_services, blockchain_services, identities_services,
-                 sources_services, transactions_services):
-        """
-        Init a new "sakia" application
-        :param QCoreApplication qapp: Qt Application
-        :param quamash.QEventLoop loop: quamash.QEventLoop instance
-        :param sakia.options.SakiaOptions options: the options
-        :param sakia.data.entities.AppData app_data: the application data
-        :param sakia.data.entities.UserParameters parameters: the application current user parameters
-        :param sakia.data.repositories.SakiaDatabase db: The database
-        :param dict network_services: All network services for current currency
-        :param dict blockchain_services: All blockchain services for current currency
-        :param dict identities_services: All identities services for current currency
-        :param dict sources_services: All sources services for current currency
-        :param dict transactions_services: All transactions services for current currency
-        :return:
-        """
+    qapp = attr.ib()
+    loop = attr.ib()
+    options = attr.ib()
+    app_data = attr.ib()
+    parameters = attr.ib()
+    db = attr.ib()
+    network_services = attr.ib(default=attr.Factory(dict))
+    blockchain_services = attr.ib(default=attr.Factory(dict))
+    identities_services = attr.ib(default=attr.Factory(dict))
+    sources_services = attr.ib(default=attr.Factory(dict))
+    transactions_services = attr.ib(default=attr.Factory(dict))
+    documents_service = attr.ib(default=None)
+    available_version = attr.ib(init=False)
+    _translator = attr.ib(init=False)
+
+    def __attrs_post_init__(self):
         super().__init__()
-        self.qapp = qapp
-        self.loop = loop
-        self.options = options
-        self.available_version = (True,
-                                  __version__,
-                                  "")
         self._translator = QTranslator(self.qapp)
-        self._app_data = app_data
-        self._parameters = parameters
-        self.db = db
-        self.network_services = network_services
-        self.blockchain_services = blockchain_services
-        self.identities_services = identities_services
-        self.sources_services = sources_services
-        self.transactions_services = transactions_services
+        self.available_version = True, __version__, ""
 
     @classmethod
     def startup(cls, argv, qapp, loop):
         options = SakiaOptions.from_arguments(argv)
         app_data = AppDataFile.in_config_path(options.config_path).load_or_init()
-        app = cls(qapp, loop, options, app_data, None, None, {}, {}, {}, {}, {})
+        app = cls(qapp, loop, options, app_data, None, None)
         #app.set_proxy()
         #app.get_last_version()
         app.load_profile(app_data.default)
         app.start_coroutines()
+        app.documents_service = DocumentsService.instanciate(app)
         #app.switch_language()
         return app
 
@@ -105,6 +102,7 @@ class Application(QObject):
         self.identities_services = {}
         self.sources_services = {}
         self.transactions_services = {}
+        self.documents_service = DocumentsService(bma_connector, blockchain_processor, identities_processor)
 
         for currency in self.db.connections_repo.get_currencies():
             if currency not in self.identities_services:
@@ -128,14 +126,6 @@ class Application(QObject):
             if currency not in self.sources_services:
                 self.sources_services[currency] = SourcesServices(currency, sources_processor, bma_connector)
 
-    def set_proxy(self):
-        if self.preferences['enable_proxy'] is True:
-            API.aiohttp_connector = ProxyConnector("http://{0}:{1}".format(
-                                    self.preferences['proxy_address'],
-                                    self.preferences['proxy_port']))
-        else:
-            API.aiohttp_connector = None
-
     def switch_language(self):
         logging.debug("Loading translations")
         locale = self.preferences['lang']
@@ -150,13 +140,6 @@ class Application(QObject):
             else:
                 logging.debug("Couldn't load translation")
 
-    @property
-    def parameters(self):
-        """
-        :rtype: sakia.data.entities.UserParameters
-        """
-        return self._parameters
-
     def start_coroutines(self):
         for currency in self.db.connections_repo.get_currencies():
             self.network_services[currency].start_coroutines()
diff --git a/src/sakia/data/processors/identities.py b/src/sakia/data/processors/identities.py
index c20da37af8fa9b8e32d03792ad4614c14f80c7d4..da208f028a1187f219604b3ba6a7682c89b22f7b 100644
--- a/src/sakia/data/processors/identities.py
+++ b/src/sakia/data/processors/identities.py
@@ -183,34 +183,4 @@ class IdentitiesProcessor:
         :param str password: The account SigningKey password
         :param str currency: The currency target of the self certification
         :param duniterpy.key.ScryptParams scrypt_params: The scrypt parameters of the key
-        """
-        blockchain = self._blockchain_repo.get_one(currency=currency)
-        block_uid = blockchain.current_buid
-        timestamp = blockchain.median_time
-        selfcert = IdentityDoc(2,
-                               currency,
-                               identity.pubkey,
-                               identity.uid,
-                               block_uid,
-                               None)
-        key = SigningKey(salt, password, scrypt_params)
-        selfcert.sign([key])
-        self._logger.debug("Key publish : {0}".format(selfcert.signed_raw()))
-
-        responses = await self._bma_connector.broadcast(currency, bma.wot.add,
-                                                        req_args={'identity': selfcert.signed_raw()})
-        result = (False, "")
-        for r in responses:
-            if r.status == 200:
-                result = (True, (await r.json()))
-            elif not result[0]:
-                result = (False, (await r.text()))
-            else:
-                await r.release()
-
-        if result[0]:
-            identity.blockstamp = block_uid
-            identity.signature = selfcert.signatures[0]
-            identity.timestamp = timestamp
-
-        return result, identity
+        """
\ No newline at end of file
diff --git a/src/sakia/gui/dialogs/certification/controller.py b/src/sakia/gui/dialogs/certification/controller.py
index 0b537e63db51744dbd15dcf246b22f88f9e788d5..c2b6bfc326d8fd1d1a6bfa59d7ab8b8f9325f2dd 100644
--- a/src/sakia/gui/dialogs/certification/controller.py
+++ b/src/sakia/gui/dialogs/certification/controller.py
@@ -115,7 +115,7 @@ class CertificationController(QObject):
         """
         self.view.button_box.setDisabled(True)
         password = await PasswordAskerDialog(self.model.connection).async_exec()
-        if password:
+        if not password:
             self.view.button_box.setEnabled(True)
             return
         QApplication.setOverrideCursor(Qt.WaitCursor)
diff --git a/src/sakia/gui/dialogs/certification/model.py b/src/sakia/gui/dialogs/certification/model.py
index 4d46e6d51d6bfcc321e2ef8eafe2b23cfc19d66b..24ed41a4f93bbae808e98184d5cd6581bd542edd 100644
--- a/src/sakia/gui/dialogs/certification/model.py
+++ b/src/sakia/gui/dialogs/certification/model.py
@@ -16,6 +16,7 @@ class CertificationModel(QObject):
     _certifications_processor = attr.ib(default=None)
     _identities_processor = attr.ib(default=None)
     _blockchain_processor = attr.ib(default=None)
+    _documents_service = attr.ib(default=None)
 
     def __attrs_post_init__(self):
         super().__init__()
@@ -90,5 +91,8 @@ class CertificationModel(QObject):
         connections = self._connections_processor.connections(currency=currency)
         self.connection = connections[index]
 
-    def certify(self, password, pubkey):
+    def certify_pubkey(self, password, pubkey):
+        self._documents_service.certify(self.connection, password, pubkey)
+
+    def certify_identity(self, password, pubkey):
         self._certifications_processor.certify(self.connection, password, pubkey)
\ No newline at end of file
diff --git a/src/sakia/gui/dialogs/connection_cfg/controller.py b/src/sakia/gui/dialogs/connection_cfg/controller.py
index 0901538858939c806e40a356c7b1a8caf3f7c846..ee9806780dbd1cd31c1a85f1503e8d4b31208aa8 100644
--- a/src/sakia/gui/dialogs/connection_cfg/controller.py
+++ b/src/sakia/gui/dialogs/connection_cfg/controller.py
@@ -156,8 +156,7 @@ class ConnectionConfigController(QObject):
                 self.view.display_info(self.tr("Broadcasting identity..."))
                 self.view.stream_log("Broadcasting identity...")
                 password = await self.password_asker.async_exec()
-                result, connection_identity = await self.model.publish_selfcert(self.model.connection.salt, password,
-                                                                                self.view.scrypt_params)
+                result, connection_identity = await self.model.publish_selfcert(password)
                 if result[0]:
                     await self.view.show_success(self.model.notification())
                 else:
diff --git a/src/sakia/gui/dialogs/connection_cfg/model.py b/src/sakia/gui/dialogs/connection_cfg/model.py
index bb0e48ceefa8801068820a240a3d75333e6e56ed..709897eeb4a263ba01f060e0babef358b7bc1d5f 100644
--- a/src/sakia/gui/dialogs/connection_cfg/model.py
+++ b/src/sakia/gui/dialogs/connection_cfg/model.py
@@ -106,15 +106,11 @@ class ConnectionConfigModel(QObject):
         transactions_processor = TransactionsProcessor.instanciate(self.app)
         await transactions_processor.initialize_transactions(identity, log_stream)
 
-    async def publish_selfcert(self, salt, password, scrypt_params):
+    async def publish_selfcert(self, password):
         """"
         Publish the self certification of the connection identity
         """
-        return await self.identities_processor.publish_selfcert(self.node_connector.node.currency,
-                                                                Identity(self.connection.currency,
-                                                                         self.connection.pubkey,
-                                                                         self.connection.uid),
-                                                                         salt, password, scrypt_params)
+        return await self.app.documents_service.broadcast_identity(self.connection, password)
 
     async def check_registered(self):
         """
diff --git a/src/sakia/services/documents.py b/src/sakia/services/documents.py
index a97a97268cf47205452a73c439825304dc37af07..73222ae4217321f7b110fee930051a7fc2e91a3a 100644
--- a/src/sakia/services/documents.py
+++ b/src/sakia/services/documents.py
@@ -6,9 +6,12 @@ from collections import Counter
 
 from duniterpy.key import SigningKey
 from duniterpy import PROTOCOL_VERSION
-from duniterpy.documents import BlockUID, Block, Identity, Certification, Membership, Revocation
+from duniterpy.documents import BlockUID, Block, Certification, Membership, Revocation
+from duniterpy.documents import Identity as IdentityDoc
 from duniterpy.api import bma, errors
-from sakia.data.entities import Node
+from sakia.data.entities import Identity
+from sakia.data.processors import BlockchainProcessor, IdentitiesProcessor, NodesProcessor
+from sakia.data.connectors import BmaConnector
 from aiohttp.errors import ClientError, DisconnectedError
 
 
@@ -21,37 +24,38 @@ class DocumentsService:
     _bma_connector = attr.ib()  # :type: sakia.data.connectors.BmaConnector
     _blockchain_processor = attr.ib()  # :type: sakia.data.processors.BlockchainProcessor
     _identities_processor = attr.ib()  # :type: sakia.data.processors.IdentitiesProcessor
-    _logger = attr.ib(default=lambda: logging.getLogger('sakia'))
+    _logger = attr.ib(default=attr.Factory(lambda: logging.getLogger('sakia')))
 
-    async def send_selfcert(self, currency, salt, password):
+    @classmethod
+    def instanciate(cls, app):
+        """
+        Instanciate a blockchain processor
+        :param sakia.app.Application app: the app
+        """
+        return cls(BmaConnector(NodesProcessor(app.db.nodes_repo)),
+                   BlockchainProcessor.instanciate(app),
+                   IdentitiesProcessor.instanciate(app))
+
+    async def broadcast_identity(self, connection, password):
         """
         Send our self certification to a target community
 
-        :param str currency: The currency of the identity
-        :param sakia.data.entities.Identity identity: The certified identity
-        :param str salt: The account SigningKey salt
-        :param str password: The account SigningKey password
+        :param sakia.data.entities.Connection connection: the connection published
         """
-        try:
-            block_data = await self._bma_connector.get(currency, bma.blockchain.Current)
-            signed_raw = "{0}{1}\n".format(block_data['raw'], block_data['signature'])
-            block_uid = Block.from_signed_raw(signed_raw).blockUID
-        except errors.DuniterError as e:
-            if e.ucode == errors.NO_CURRENT_BLOCK:
-                block_uid = BlockUID.empty()
-            else:
-                raise
-        selfcert = Identity(PROTOCOL_VERSION,
-                                     currency,
-                                     self.pubkey,
-                                     self.name,
-                                     block_uid,
-                                     None)
-        key = SigningKey(salt, password)
+        block_uid = self._blockchain_processor.current_buid(connection.currency)
+        timestamp = self._blockchain_processor.time(connection.currency)
+        selfcert = IdentityDoc(2,
+                               connection.currency,
+                               connection.pubkey,
+                               connection.uid,
+                               block_uid,
+                               None)
+        key = SigningKey(connection.salt, password, connection.scrypt_params)
         selfcert.sign([key])
         self._logger.debug("Key publish : {0}".format(selfcert.signed_raw()))
 
-        responses = await self._bma_connector.broadcast(currency, bma.wot.Add, {}, {'identity': selfcert.signed_raw()})
+        responses = await self._bma_connector.broadcast(connection.currency, bma.wot.add,
+                                                        req_args={'identity': selfcert.signed_raw()})
         result = (False, "")
         for r in responses:
             if r.status == 200:
@@ -60,7 +64,16 @@ class DocumentsService:
                 result = (False, (await r.text()))
             else:
                 await r.release()
-        return result
+
+        if result[0]:
+            identity = self._identities_processor.get_identity(connection.currency, connection.pubkey, connection.uid)
+            if not identity:
+                identity = Identity(connection.currency, connection.pubkey, connection.uid)
+            identity.blockstamp = block_uid
+            identity.signature = selfcert.signatures[0]
+            identity.timestamp = timestamp
+
+        return result, identity
 
     async def send_membership(self, currency, identity, salt, password, mstype):
         """
@@ -68,7 +81,7 @@ class DocumentsService:
         Signal "document_broadcasted" is emitted at the end.
 
         :param str currency: the currency target
-        :param sakia.data.entities.Identity identity: the identitiy data
+        :param sakia.data.entities.IdentityDoc identity: the identitiy data
         :param str salt: The account SigningKey salt
         :param str password: The account SigningKey password
         :param str mstype: The type of membership demand. "IN" to join, "OUT" to leave
@@ -99,7 +112,7 @@ class DocumentsService:
         Certify an other identity
 
         :param str currency: The currency of the identity
-        :param sakia.data.entities.Identity identity: The certified identity
+        :param sakia.data.entities.IdentityDoc identity: The certified identity
         :param str salt: The account SigningKey salt
         :param str password: The account SigningKey password
         """
@@ -133,7 +146,7 @@ class DocumentsService:
         Revoke self-identity on server, not in blockchain
 
         :param str currency: The currency of the identity
-        :param sakia.data.entities.Identity identity: The certified identity
+        :param sakia.data.entities.IdentityDoc identity: The certified identity
         :param str salt: The account SigningKey salt
         :param str password: The account SigningKey password
         """
@@ -168,7 +181,7 @@ class DocumentsService:
         Generate account revokation document for given community
 
         :param str currency: The currency of the identity
-        :param sakia.data.entities.Identity identity: The certified identity
+        :param sakia.data.entities.IdentityDoc identity: The certified identity
         :param str salt: The account SigningKey salt
         :param str password: The account SigningKey password
         """
diff --git a/src/sakia/tests/conftest.py b/src/sakia/tests/conftest.py
index eb5cf52bdad90b0bfce99e713e66f2e8591d0ba7..bab6a63b706b0427ddbc40cbe879aa98f1d5e3ef 100644
--- a/src/sakia/tests/conftest.py
+++ b/src/sakia/tests/conftest.py
@@ -9,6 +9,7 @@ from sakia.options import SakiaOptions
 from sakia.data.files import AppDataFile
 from sakia.data.entities import *
 from sakia.data.repositories import *
+from sakia.services import DocumentsService
 
 
 _application_ = []
@@ -61,7 +62,14 @@ def user_parameters():
 
 @pytest.fixture
 def application(event_loop, meta_repo, sakia_options, app_data, user_parameters):
-    return Application(get_application(), event_loop, sakia_options, app_data, user_parameters, meta_repo, {}, {}, {}, {}, {})
+    app = Application(qapp=get_application(),
+                       loop=event_loop,
+                       options=sakia_options,
+                       app_data=app_data,
+                       parameters=user_parameters,
+                       db=meta_repo)
+    app.documents_service = DocumentsService.instanciate(app)
+    return app
 
 
 @pytest.fixture
diff --git a/src/sakia/tests/functional/test_certification_dialog.py b/src/sakia/tests/functional/test_certification_dialog.py
index a95f107c68f76181e7f9429b509c5050a4288d9a..d2e5c49bfe438ff95a70c67b8fb0d128ac6961b0 100644
--- a/src/sakia/tests/functional/test_certification_dialog.py
+++ b/src/sakia/tests/functional/test_certification_dialog.py
@@ -20,6 +20,7 @@ async def test_certification_init_community(application_with_one_connection, fak
         certification_dialog.view.radio_pubkey.setChecked(True)
         assert certification_dialog.view.edit_pubkey.isEnabled() is True
         QTest.keyClicks(certification_dialog.view.edit_pubkey, alice.key.pubkey)
+        await asyncio.sleep(0.1)
         QTest.mouseClick(certification_dialog.view.button_box.button(QDialogButtonBox.Ok), Qt.LeftButton)
         await asyncio.sleep(0.1)
         assert Certification is type(fake_server.forge.pool[0])