diff --git a/src/sakia/app.py b/src/sakia/app.py
index 79cb71edc9a48cf9a6f94fd9cbd2bbc16f0c29ce..b83ae53f1c1cbac8dd94488667ebfa45dbe25999 100644
--- a/src/sakia/app.py
+++ b/src/sakia/app.py
@@ -117,7 +117,8 @@ class Application(QObject):
 
             if currency not in self.transactions_services:
                 self.transactions_services[currency] = TransactionsService(currency, transactions_processor,
-                                                                       identities_processor, bma_connector)
+                                                                       identities_processor, connections_processor,
+                                                                       bma_connector)
 
             if currency not in self.blockchain_services:
                 self.blockchain_services[currency] = BlockchainService(self, currency, blockchain_processor, bma_connector,
diff --git a/src/sakia/data/entities/transaction.py b/src/sakia/data/entities/transaction.py
index a014b2de2e565608dd02ef75e19391bec377053f..fb5e1666f66d5b3df9a7f57341a784ee1e77cd18 100644
--- a/src/sakia/data/entities/transaction.py
+++ b/src/sakia/data/entities/transaction.py
@@ -78,15 +78,13 @@ class Transaction:
     :param str amount_base: the amount base
     :param str comment: a comment
     :param str txid: the transaction id to sort transctions
-    :param str state: the state of the transaction
+    :param int state: the state of the transaction
     """
     TO_SEND = 0
     AWAITING = 1
-    VALIDATING = 2
     VALIDATED = 4
     REFUSED = 8
     DROPPED = 16
-    LOCAL = 128
 
     currency      = attr.ib(convert=str, cmp=False)
     sha_hash      = attr.ib(convert=str)
@@ -102,8 +100,3 @@ class Transaction:
     txid          = attr.ib(convert=int, cmp=False)
     state         = attr.ib(convert=int, cmp=False)
     raw           = attr.ib(convert=str, cmp=False, default="")
-
-
-    @property
-    def local(self):
-        return self.state & Transaction.LOCAL == Transaction.LOCAL
diff --git a/src/sakia/data/processors/transactions.py b/src/sakia/data/processors/transactions.py
index d573ff0a9ee6a1af13c5f576e415384506ce6933..71d06be76e2f37c7615b8f8fef4a4eb2a88325c9 100644
--- a/src/sakia/data/processors/transactions.py
+++ b/src/sakia/data/processors/transactions.py
@@ -1,3 +1,4 @@
+import logging
 import attr
 import asyncio
 import sqlite3
@@ -16,6 +17,7 @@ class TransactionsProcessor:
     _repo = attr.ib()  # :type sakia.data.repositories.SourcesRepo
     _bma_connector = attr.ib()  # :type sakia.data.connectors.bma.BmaConnector
     _table_states = attr.ib(default=attr.Factory(dict))
+    _logger = attr.ib(default=attr.Factory(lambda: logging.getLogger('sakia')))
 
     @classmethod
     def instanciate(cls, app):
@@ -57,30 +59,35 @@ class TransactionsProcessor:
         """
         if len(inputs) == len(transition_key[1]):
             for i, input in enumerate(inputs):
-                if type(input) is not transition_key[1][i]:
+                if not isinstance(input, transition_key[1][i]):
                     return False
             for transition in tx_lifecycle.states[transition_key]:
-                if transition[0](*inputs):
+                if transition[0](tx, *inputs):
                     if tx.sha_hash:
                         self._logger.debug("{0} : {1} --> {2}".format(tx.sha_hash[:5], tx.state,
-                                                                 transition[2].name))
+                                                                      transition[2]))
                     else:
                         self._logger.debug("Unsent transfer : {0} --> {1}".format(tx.state,
-                                                                             transition[2].name))
+                                                                                  transition[2]))
 
                     # If the transition changes data, apply changes
                     if transition[1]:
                         transition[1](tx, *inputs)
-                    tx.state = transition[2] | tx.local
+                    tx.state = transition[2]
                     return True
         return False
 
+    def commit(self, tx):
+        try:
+            self._repo.insert(tx)
+        except sqlite3.IntegrityError:
+            self._repo.update(tx)
+
     def find_by_hash(self, sha_hash):
-        return self._repo.find_one(sha_hash=sha_hash)
+        return self._repo.get_one(sha_hash=sha_hash)
 
     def awaiting(self, currency):
-        return self._repo.get_all(currency=currency, state=Transaction.AWAITING) + \
-               self._repo.get_all(currency=currency, state=Transaction.AWAITING | Transaction.LOCAL)
+        return self._repo.get_all(currency=currency, state=Transaction.AWAITING)
 
     def run_state_transitions(self, tx, *inputs):
         """
@@ -90,9 +97,10 @@ class TransactionsProcessor:
         :return: True if the transaction changed state
         :rtype: bool
         """
-        transition_keys = [k for k in tx_lifecycle.states.keys() if k[0] | Transaction.LOCAL == tx.state]
+        transition_keys = [k for k in tx_lifecycle.states.keys() if k[0] == tx.state]
         for key in transition_keys:
             if self._try_transition(tx, key, inputs):
+                self._repo.update(tx)
                 return True
         return False
 
@@ -123,7 +131,7 @@ class TransactionsProcessor:
                 result = (False, (await r.text()))
             else:
                 await r.text()
-        self.run_state_transitions(tx, ([r.status for r in responses],))
+        self.run_state_transitions(tx, [r.status for r in responses])
         return result, tx
 
     async def initialize_transactions(self, identity, log_stream):
diff --git a/src/sakia/data/processors/tx_lifecycle.py b/src/sakia/data/processors/tx_lifecycle.py
index 7769bab6d77f76cd2374d968f4281064df6e8d83..37b89567dcc9102a846434ce3eafc568b02ebe24 100644
--- a/src/sakia/data/processors/tx_lifecycle.py
+++ b/src/sakia/data/processors/tx_lifecycle.py
@@ -3,43 +3,20 @@ from sakia.data.entities import Transaction
 from duniterpy.documents import Block
 
 
-def _not_found_in_blockchain(tx, rollback, block, mediantime_target, mediantime_blocks):
-    """
-    Check if the transaction could not be found in the blockchain
-    :param sakia.data.entities.Transaction tx: the transaction
-    :param bool rollback: True if we are in a rollback procedure
-    :param duniterpy.documents.Block block: The block to look for the tx
-    :param int mediantime_target: The mediantime to mine a block in the community parameters
-    :param int mediantime_blocks: The number of block used to derive the mediantime
-    :return: True if the transaction could not be found in a given time
-    :rtype: bool
-    """
-    if not rollback:
-        for block_tx in block.transactions:
-            if block_tx.sha_hash == tx.sha_hash:
-                return False
-        if block.time > tx.timestamp + mediantime_target * mediantime_blocks:
-            return True
-    return False
-
-
-def _found_in_block(tx, rollback, block):
+def _found_in_block(tx, block):
     """
     Check if the transaction can be found in the blockchain
     :param sakia.data.entities.Transaction tx: the transaction
-    :param bool rollback: True if we are in a rollback procedure
     :param duniterpy.documents.Block block: The block to check for the transaction
     :return: True if the transaction was found
     :rtype: bool
     """
-    if not rollback:
-        for block_tx in block.transactions:
-            if block_tx.sha_hash == tx.sha_hash:
-                return True
-    return False
+    for block_tx in block.transactions:
+        if block_tx.sha_hash == tx.sha_hash:
+            return True
 
 
-def _broadcast_success(tx, ret_codes, block):
+def _broadcast_success(tx, ret_codes):
     """
     Check if the retcode is 200 after a POST
     :param sakia.data.entities.Transaction tx: the transaction
@@ -62,19 +39,6 @@ def _broadcast_failure(tx, ret_codes):
     return 200 not in ret_codes
 
 
-def _reached_enough_confrmation(tx, rollback, current_block, fork_window):
-    """
-    Check if the transfer reached enough confrmation in the blockchain
-    :param sakia.data.entities.Transaction tx: the transaction
-    :param bool rollback: True if we are in a rollback procedure
-    :param duniterpy.documents.Block current_block: The current block of the main blockchain
-    :param int fork_window: The number of confrmations needed on the network
-    :return: True if the transfer reached enough confrmations
-    :rtype: bool
-    """
-    return not rollback and tx.blockstamp.number + fork_window <= current_block.number
-
-
 def _rollback_and_removed(tx, rollback, block):
     """
     Check if the transfer is not in the block anymore
@@ -92,20 +56,6 @@ def _rollback_and_removed(tx, rollback, block):
     return False
 
 
-def _rollback_in_fork_window(tx, rollback, current_block, fork_window):
-    """
-    Check if the transfer is not in the block anymore
-
-    :param sakia.data.entities.Transaction tx: the transaction
-    :param bool rollback: True if we are in a rollback procedure
-    :param duniterpy.documents.Block current_block: The block to check for the transaction
-    :return: True if the transfer is found in the block
-    """
-    if rollback:
-        return tx.blockstamp.number + fork_window > current_block.number
-    return False
-
-
 def _rollback_and_local(tx, rollback, block):
     """
     Check if the transfer is not in the block anymore
@@ -129,7 +79,8 @@ def _is_locally_created(tx):
     """
     return tx.local
 
-def _be_validating(tx, block):
+
+def _be_validated(tx, block):
     """
     Action when the transfer ins found in a block
 
@@ -162,18 +113,8 @@ states = {
             (Transaction.TO_SEND, ()):
                 ((_is_locally_created, _drop, Transaction.DROPPED),),
 
-            (Transaction.AWAITING, (bool, Block)):
-                ((_found_in_block, lambda tx, r, b: _be_validating(tx, b), Transaction.VALIDATING),),
-            (Transaction.AWAITING, (bool, Block, int, int)):
-                ((_not_found_in_blockchain, None, Transaction.REFUSED),),
-
-            (Transaction.VALIDATING, (bool, Block, int)):
-                ((_reached_enough_confrmation, None, Transaction.VALIDATED),),
-            (Transaction.VALIDATING, (bool, Block)):
-                ((_rollback_and_removed, lambda tx, r, b: _drop(tx), Transaction.DROPPED),),
-
-            (Transaction.VALIDATED, (bool, Block, int)):
-                ((_rollback_in_fork_window, lambda tx, r, b, i: _be_validating(tx, b), Transaction.VALIDATING),),
+            (Transaction.AWAITING, (Block,)):
+                ((_found_in_block, _be_validated, Transaction.VALIDATED),),
 
             (Transaction.VALIDATED, (bool,)):
                 (
diff --git a/src/sakia/gui/navigation/txhistory/table_model.py b/src/sakia/gui/navigation/txhistory/table_model.py
index c587b9d2153e89b8b051300288127ae299a86608..a8d6e5d5e60fc4ecbab09d8a0410ed81a58c72b9 100644
--- a/src/sakia/gui/navigation/txhistory/table_model.py
+++ b/src/sakia/gui/navigation/txhistory/table_model.py
@@ -157,18 +157,20 @@ class TxFilterProxyModel(QSortFilterProxyModel):
             if source_index.column() == self.sourceModel().columns_types.index('date'):
                 return QDateTime.fromTime_t(source_data).toString(Qt.SystemLocaleLongDate)
 
-            if state_data == Transaction.VALIDATING or state_data == Transaction.AWAITING:
+            if state_data == Transaction.VALIDATED or state_data == Transaction.AWAITING:
                 block_col = model.columns_types.index('block_number')
                 block_index = model.index(source_index.row(), block_col)
                 block_data = model.data(block_index, Qt.DisplayRole)
 
                 current_confirmations = 0
-                if state_data == Transaction.VALIDATING:
+                if state_data == Transaction.VALIDATED:
                     current_confirmations = self.blockchain_service.current_buid().number - block_data
                 elif state_data == Transaction.AWAITING:
                     current_confirmations = 0
 
-                if self.app.preferences['expert_mode']:
+                if current_confirmations >= MAX_CONFIRMATIONS:
+                    return None
+                elif self.app.preferences['expert_mode']:
                     return self.tr("{0} / {1} confirmations").format(current_confirmations, MAX_CONFIRMATIONS)
                 else:
                     confirmation = current_confirmations / MAX_CONFIRMATIONS * 100
diff --git a/src/sakia/services/blockchain.py b/src/sakia/services/blockchain.py
index 1de1e7f8b546e8d2049c9e4a879594b2c2c8282c..3e813eb1a3c419607e4865650be30dfad8828ddc 100644
--- a/src/sakia/services/blockchain.py
+++ b/src/sakia/services/blockchain.py
@@ -39,7 +39,7 @@ class BlockchainService(QObject):
             with_money = await self._blockchain_processor.new_blocks_with_money(self.currency)
             blocks = await self._blockchain_processor.blocks(with_identities + with_money, self.currency)
             await self._identities_service.handle_new_blocks(blocks)
-            await self._transactions_service.handle_new_blocks(blocks)
+            self._transactions_service.handle_new_blocks(blocks)
             self.app.db.commit()
         except (NoPeerAvailable, DuniterError) as e:
             self._logger.debug(str(e))
diff --git a/src/sakia/services/transactions.py b/src/sakia/services/transactions.py
index 99b72e4cdc49ac2999ed8c061302cb0c0daac2e2..6bd563cec855b523a38e6c8b77421b0dff43d85e 100644
--- a/src/sakia/services/transactions.py
+++ b/src/sakia/services/transactions.py
@@ -9,23 +9,25 @@ class TransactionsService(QObject):
     Transaction service is managing sources received
     to update data locally
     """
-    def __init__(self, currency, transactions_processor, identities_processor, bma_connector):
+    def __init__(self, currency, transactions_processor, identities_processor, connections_processor, bma_connector):
         """
         Constructor the identities service
 
         :param str currency: The currency name of the community
         :param sakia.data.processors.IdentitiesProcessor identities_processor: the identities processor for given currency
         :param sakia.data.processors.TransactionsProcessor transactions_processor: the transactions processor for given currency
+        :param sakia.data.processors.ConnectionsProcessor connections_processor: the connections processor for given currency
         :param sakia.data.connectors.BmaConnector bma_connector: The connector to BMA API
         """
         super().__init__()
         self._transactions_processor = transactions_processor
         self._identities_processor = identities_processor
+        self._connections_processor = connections_processor
         self._bma_connector = bma_connector
         self.currency = currency
         self._logger = logging.getLogger('sakia')
 
-    async def _parse_block(self, block_doc, txid):
+    def _parse_block(self, block_doc, txid):
         """
         Parse a block
         :param duniterpy.documents.Block block_doc: The block
@@ -34,22 +36,23 @@ class TransactionsService(QObject):
         """
         transfers = []
         for tx in [t for t in self._transactions_processor.awaiting(self.currency)]:
-            self._transactions_processor.run_state_transitions(tx, (False, block_doc))
+            self._transactions_processor.run_state_transitions(tx, block_doc)
 
-            new_transactions = [t for t in block_doc.transactions
-                                    if not self._transactions_processor.find_by_hash(t.sha_hash)
-                                    and SimpleTransaction.is_simple(t)]
-
-            for (i, tx_doc) in enumerate(new_transactions):
-                tx = parse_transaction_doc(tx_doc, block_doc.blockUID.number,  block_doc.mediantime, txid+i)
+        new_transactions = [t for t in block_doc.transactions
+                            if not self._transactions_processor.find_by_hash(t.sha_hash)
+                            and SimpleTransaction.is_simple(t)]
+        connections_pubkeys = [c.pubkey for c in self._connections_processor.connections_to(self.currency)]
+        for (i, tx_doc) in enumerate(new_transactions):
+            for pubkey in connections_pubkeys:
+                tx = parse_transaction_doc(tx_doc, pubkey, block_doc.blockUID.number,  block_doc.mediantime, txid+i)
                 if tx:
-                    #logging.debug("Transfer amount : {0}".format(transfer.metadata['amount']))
+                    transfers.append(tx)
                     self._transactions_processor.commit(tx)
                 else:
                     logging.debug("Error during transfer parsing")
         return transfers
 
-    async def handle_new_blocks(self, blocks):
+    def handle_new_blocks(self, blocks):
         """
         Refresh last transactions
 
@@ -58,7 +61,7 @@ class TransactionsService(QObject):
         self._logger.debug("Refresh transactions")
         txid = 0
         for block in blocks:
-            transfers = await self._parse_block(block, txid)
+            transfers = self._parse_block(block, txid)
             txid += len(transfers)
 
     def transfers(self, pubkey):
diff --git a/src/sakia/tests/technical/test_identities_service.py b/src/sakia/tests/technical/test_identities_service.py
index 0ef3ade60dfcb233786cdd30bf9033c764c2e2bc..d2e2bb9cf26ae6a4fa92d9828edf8a379cb02209 100644
--- a/src/sakia/tests/technical/test_identities_service.py
+++ b/src/sakia/tests/technical/test_identities_service.py
@@ -1,38 +1,6 @@
-import unittest
-import sqlite3
-from duniterpy.documents import BlockUID, Block
-from sakia.tests.mocks.bma.nice_blockchain import bma_blockchain_0
-from sakia.tests import QuamashTest
-from sakia.services import IdentitiesService
-from sakia.data.repositories import CertificationsRepo, IdentitiesRepo, SakiaDatabase
-from sakia.data.processors import CertificationsProcessor, IdentitiesProcessor
+import pytest
 
 
-class TestIdentitiesService(unittest.TestCase, QuamashTest):
-    def setUp(self):
-        self.setUpQuamash()
-        sqlite3.register_adapter(BlockUID, str)
-        sqlite3.register_adapter(bool, int)
-        sqlite3.register_adapter(list, lambda ls: '\n'.join([str(v) for v in ls]))
-        sqlite3.register_adapter(tuple, lambda ls: '\n'.join([str(v) for v in ls]))
-        sqlite3.register_converter("BOOLEAN", lambda v: bool(int(v)))
-        self.con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
-
-    def tearDown(self):
-        self.tearDownQuamash()
-
-    def test_new_block_with_unknown_identities(self):
-        meta_repo = SakiaDatabase(self.con)
-        meta_repo.prepare()
-        meta_repo.upgrade_database()
-        identities_repo = IdentitiesRepo(self.con)
-        certs_repo = CertificationsRepo(self.con)
-        identities_processor = IdentitiesProcessor("testcurrency", identities_repo, None)
-        certs_processor = CertificationsProcessor("testcurrency", certs_repo, None)
-        identities_service = IdentitiesService("testcurrency", identities_processor, certs_processor, None)
-        block = Block.from_signed_raw("{0}{1}\n".format(bma_blockchain_0["raw"], bma_blockchain_0["signature"]))
-        identities_service.parse_block(block)
-        self.assertEqual(identities_processor.get_written("8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU"), [])
-        self.assertEqual(identities_processor.get_written("HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"), [])
-        self.assertEqual(identities_processor.get_written("BMAVuMDcGhYAV4wA27DL1VXX2ZARZGJYaMwpf7DJFMYH"), [])
-        self.assertEqual(identities_processor.get_written("37qBxM4hLV2jfyYo2bNzAjkeLngLr2r7G2HpdpKieVxw"), [])
+@pytest.mark.asyncio
+async def test_new_block_with_unknown_identities(application_with_one_connection, fake_server, bob, alice):
+    pass
\ No newline at end of file
diff --git a/src/sakia/tests/technical/test_transactions_service.py b/src/sakia/tests/technical/test_transactions_service.py
new file mode 100644
index 0000000000000000000000000000000000000000..dfbdfbcdead2728acbc331b0e07ed3d840bd2f19
--- /dev/null
+++ b/src/sakia/tests/technical/test_transactions_service.py
@@ -0,0 +1,39 @@
+import pytest
+from sakia.data.entities import Transaction
+
+
+@pytest.mark.asyncio
+async def test_send_tx_then_validate(application_with_one_connection, fake_server, bob, alice):
+    tx_before_send = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    bob_connection = application_with_one_connection.db.connections_repo.get_one(pubkey=bob.key.pubkey)
+    await application_with_one_connection.documents_service.send_money(bob_connection,
+                                                                 bob.password,
+                                                                 alice.key.pubkey, 10, 0, "Test comment")
+    tx_after_send = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    assert len(tx_before_send) + 1 == len(tx_after_send)
+    assert tx_after_send[-1].state is Transaction.AWAITING
+    fake_server.forge.forge_block()
+    fake_server.forge.forge_block()
+    fake_server.forge.forge_block()
+    new_blocks = fake_server.forge.blocks[-3:]
+    application_with_one_connection.transactions_services[fake_server.forge.currency].handle_new_blocks(new_blocks)
+    tx_after_parse = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    assert tx_after_parse[-1].state is Transaction.VALIDATED
+    await fake_server.close()
+
+
+@pytest.mark.asyncio
+async def test_receive_tx(application_with_one_connection, fake_server, bob, alice):
+    tx_before_send = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    fake_server.forge.push(alice.send_money(10, fake_server.forge.user_identities[alice.key.pubkey].sources, bob,
+                                            fake_server.forge.blocks[-1].blockUID, "Test receive"))
+    fake_server.forge.forge_block()
+    fake_server.forge.forge_block()
+    fake_server.forge.forge_block()
+    new_blocks = fake_server.forge.blocks[-3:]
+    application_with_one_connection.transactions_services[fake_server.forge.currency].handle_new_blocks(new_blocks)
+    tx_after_parse = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    assert tx_after_parse[-1].state is Transaction.VALIDATED
+    assert len(tx_before_send) + 1 == len(tx_after_parse)
+    await fake_server.close()
+
diff --git a/src/sakia/tests/unit/data/test_transactions_repo.py b/src/sakia/tests/unit/data/test_transactions_repo.py
index 8582943e037b747984ef9e944ac00366d39bf472..6b2010d5c31856c2bf6cc31f4173c15f0f537e13 100644
--- a/src/sakia/tests/unit/data/test_transactions_repo.py
+++ b/src/sakia/tests/unit/data/test_transactions_repo.py
@@ -1,6 +1,5 @@
 from sakia.data.repositories import TransactionsRepo
 from sakia.data.entities import Transaction
-from duniterpy.documents import BlockUID
 
 
 def test_add_get_drop_transaction(meta_repo):
@@ -17,7 +16,7 @@ def test_add_get_drop_transaction(meta_repo):
                                          1,
                                          "",
                                          0,
-                                         Transaction.LOCAL))
+                                         Transaction.TO_SEND))
     transaction = transactions_repo.get_one(sha_hash="FCAD5A388AC8A811B45A9334A375585E77071AA9F6E5B6896582961A6C66F365")
     assert transaction.currency == "testcurrency"
     assert transaction.sha_hash == "FCAD5A388AC8A811B45A9334A375585E77071AA9F6E5B6896582961A6C66F365"
@@ -51,7 +50,7 @@ def test_add_get_multiple_transaction(meta_repo):
                                          2,
                                          "Test",
                                          2,
-                                         Transaction.LOCAL))
+                                         Transaction.TO_SEND))
     transactions_repo.insert(Transaction("testcurrency",
                                          "FCAD5A388AC8A811B45A9334A375585E77071AA9F6E5B6896582961A6C66F365",
                                          20,
@@ -64,7 +63,7 @@ def test_add_get_multiple_transaction(meta_repo):
                                          1,
                                          "",
                                          0,
-                                         Transaction.LOCAL))
+                                         Transaction.TO_SEND))
     transactions = transactions_repo.get_all(currency="testcurrency")
     assert "testcurrency" in [t.currency for t in transactions]
     assert "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ" in [t.receiver for t in transactions]
@@ -85,7 +84,7 @@ def test_add_update_transaction(meta_repo):
                               1,
                               "",
                               0,
-                              Transaction.LOCAL)
+                              Transaction.TO_SEND)
     transactions_repo.insert(transaction)
     transaction.written_on = None
     transactions_repo.update(transaction)