diff --git a/release.sh b/release.sh
index d59745356ecfc9aefa37debf189ba705ef888992..4524609cf798ccfb971caa25514c4f1261985d7e 100755
--- a/release.sh
+++ b/release.sh
@@ -90,6 +90,9 @@ if [[ $2 =~ ^[0-9]+.[0-9]+.[0-9]+((a|b)[0-9]+)?$ && $3 =~ ^[0-9]+$ ]]; then
     echo "- Building desktop versions..."
     echo "----------------------------------"
 
+    # Remove old vagrant virtual machines
+    rm -rf ~/.vagrant.d/*
+
     git submodule update --init
     git submodule sync
     cd platforms/desktop
diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss
index e58699ee122e25595e518317da09be0a7c78fc75..44051ac7d5cfdced4d3edaff1170da2f4fe0288b 100644
--- a/scss/ionic.app.scss
+++ b/scss/ionic.app.scss
@@ -1306,6 +1306,7 @@ a.underline:hover,
   }
 }
 
+
 /**********
    Form validation
 **********/
diff --git a/www/i18n/locale-en-GB.json b/www/i18n/locale-en-GB.json
index 4dd8db337f7d8f38e23b0c5d997b371647c6e581..c19c8e56888a31983c339ffc60b3ee308e7ed2fc 100644
--- a/www/i18n/locale-en-GB.json
+++ b/www/i18n/locale-en-GB.json
@@ -617,6 +617,7 @@
     "IDENTITY_EXPIRED": "This identity has expired: this person must re-apply <b>before</b> being certified.",
     "IDENTITY_SANDBOX_FULL": "Could not register, because peer's sandbox is full.<br/><br/>Please retry later or choose another Duniter peer (in <b>Settings</b>).",
     "IDENTITY_NOT_FOUND": "Identity not found",
+    "IDENTITY_TX_FAILED": "Error while getting identity's transactions",
     "WOT_PENDING_INVALID_BLOCK_HASH": "Membership not valid.",
     "WALLET_INVALID_BLOCK_HASH": "Your membership application is no longer valid (because it references a block that network peers are cancelled).<br/>You must <a ng-click=\"doQuickFix('renew')\">renew your application for membership</a> to fix this issue.",
     "WALLET_IDENTITY_EXPIRED": "The publication of your identity <b>has expired</b>.<br/>You must <a ng-click=\"doQuickFix('fixIdentity')\">re-issue your identity</a> to resolve this issue.",
diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json
index 6e4347d65240e0dc8f17727fdf318eb595ef41ea..6c77fc94eec1dd60b560a97e95bf48be923e6368 100644
--- a/www/i18n/locale-en.json
+++ b/www/i18n/locale-en.json
@@ -617,6 +617,7 @@
     "IDENTITY_EXPIRED": "This identity has expired: this person must re-apply <b>before</b> being certified.",
     "IDENTITY_SANDBOX_FULL": "Could not register, because peer's sandbox is full.<br/><br/>Please retry later or choose another Duniter peer (in <b>Settings</b>).",
     "IDENTITY_NOT_FOUND": "Identity not found",
+    "IDENTITY_TX_FAILED": "Error while getting identity's transactions",
     "WOT_PENDING_INVALID_BLOCK_HASH": "Membership not valid.",
     "WALLET_INVALID_BLOCK_HASH": "Your membership application is no longer valid (because it references a block that network peers are cancelled).<br/>You must <a ng-click=\"doQuickFix('renew')\">renew your application for membership</a> to fix this issue.",
     "WALLET_IDENTITY_EXPIRED": "The publication of your identity <b>has expired</b>.<br/>You must <a ng-click=\"doQuickFix('fixIdentity')\">re-issue your identity</a> to resolve this issue.",
diff --git a/www/i18n/locale-es-ES.json b/www/i18n/locale-es-ES.json
index 6741c10dea408981f2ee485904015a07e54dba6e..27485257c6c379eed81be5f954c43de30360d397 100644
--- a/www/i18n/locale-es-ES.json
+++ b/www/i18n/locale-es-ES.json
@@ -565,11 +565,17 @@
     "IDENTITY_EXPIRED": "La publicación de esta identidad ha caducada : esta persona debe realizar una nueva solicitud de adhesión <b>antes que</b> estar certificada.",
     "IDENTITY_SANDBOX_FULL": "EL nodo Duniter utilizado por Cesium ya no puede recibir más nuevas identidades, porque la fila de espera es llena.<br/><br/>Por favor, intenta ulteriormente o cambia de nodo (vía el menú <b>Paramètres</b>).",
     "IDENTITY_NOT_FOUND": "Identidad no encontrada",
+    "IDENTITY_TX_FAILED": "Las operaciones de carga fallidos",
     "WOT_PENDING_INVALID_BLOCK_HASH": "Adhesión no validada.",
     "WALLET_INVALID_BLOCK_HASH": "Su solicitud de adhesión ya no está validada (porque denomina un bloque los nodos de la red han anulado).<br/>Debe <a ng-click=\"doQuickFix('fixMembership')\">mandar una nueva solicitud</a> para resolver este problema.",
     "WALLET_IDENTITY_EXPIRED": "La publicación de <b>su identidad ha caducada</b>.<br/>Debe <a ng-click=\"doQuickFix('fixIdentity')\">publicar une outra vez su identidad</a> para resolver este problema.",
     "WALLET_REVOKED": "Su identidad fue <b>revocada</b> : ni su seudónimo ni su llave pública podrán estar utilizados en el futuro por una cuenta miembro.",
     "WALLET_HAS_NO_SELF": "Su identidad debe en primer lugar haber estado publicado, y no estar caducada.",
+    "AUTH_REQUIRED": "Autenticación requerida.",
+    "AUTH_INVALID_PUBKEY": "La llave pública no se corresponde con la cuenta conectada",
+    "AUTH_INVALID_SCRYPT": "De usuario o contraseña no válidos.",
+    "AUTH_INVALID_FILE": "archivo de llave no válido.",
+    "AUTH_FILE_ERROR": "No se pudo abrir el archivo de llave",
     "IDENTITY_ALREADY_CERTIFY": "Ha <b>ya certificado</b> esta identidad.<br/><br/>Esta certificación todavía es valida (expiration {{expiresIn|formatDurationTo}}).",
     "IDENTITY_ALREADY_CERTIFY_PENDING": "Ha <b>ya certificado</b> esta identidad.<br/><br/>Esta certificación está en espera de tratamiento (fecha límite de tratamiento {{expiresIn|formatDurationTo}}).",
     "UNABLE_TO_CERTIFY_TITLE": "Certificación imposible",
diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json
index 41a2581102333f769de6b18d4db69589a2ef6060..142bc212fa329a76c28f16465dc61266df08eff2 100644
--- a/www/i18n/locale-fr-FR.json
+++ b/www/i18n/locale-fr-FR.json
@@ -437,7 +437,7 @@
     "EVENTS": "Evénements",
     "WAITING_MEMBERSHIP": "Demande d'adhésion envoyée. En attente d'acceptation.",
     "WAITING_CERTIFICATIONS": "Vous devez obtenir {{needCertificationCount}} certification(s) pour devenir membre.",
-    "WILL_MISSING_CERTIFICATIONS": "Vous allez bientôt <b>manquer de certification</b> (au moins {{willNeedCertificationCount}} est nécessaire)",
+    "WILL_MISSING_CERTIFICATIONS": "Vous allez bientôt <b>manquer de certification</b> (au moins {{willNeedCertificationCount}} sont requises)",
     "WILL_NEED_RENEW_MEMBERSHIP": "Votre adhésion comme membre <b>va expirer {{membershipExpiresIn|formatDurationTo}}</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a> d'ici là.",
     "NEED_RENEW_MEMBERSHIP": "Vous n'êtes plus membre, car votre adhésion <b>a expiré</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a>.",
     "CERTIFICATION_COUNT": "Certifications reçues",
@@ -617,6 +617,7 @@
     "IDENTITY_EXPIRED": "La publication de cette identité a expirée : cette personne doit effectuer une nouvelle demande d'adhésion <b>avant</b> d'être certifiée.",
     "IDENTITY_SANDBOX_FULL": "Le nœud Duniter utilisé par Cesium ne peut plus recevoir de nouvelles identités, car sa file d'attente est pleine.<br/><br/>Veuillez réessayer ultérieurement ou changer de nœud (via le menu <b>Paramètres</b>).",
     "IDENTITY_NOT_FOUND": "Identité non trouvée",
+    "IDENTITY_TX_FAILED": "Echec du chargement des opérations",
     "WOT_PENDING_INVALID_BLOCK_HASH": "Adhésion non valide.",
     "WALLET_INVALID_BLOCK_HASH": "Votre demande d'adhésion n'est plus valide (car elle référence un bloc que les nœuds du réseau ont annulé).<br/>Vous devez <a ng-click=\"doQuickFix('fixMembership')\">envoyer une nouvelle demande</a> pour résoudre ce problème.",
     "WALLET_IDENTITY_EXPIRED": "La publication de <b>votre identité a expirée</b>.<br/>Vous devez <a ng-click=\"doQuickFix('fixIdentity')\">publier à nouveau votre identité</a> pour résoudre ce problème.",
diff --git a/www/js/app.js b/www/js/app.js
index 8c280a5eba4d26b47b923f43e114763ef55211d3..6b52789d4e34b48fb4c896995d8fd3f6929ea8af 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -258,7 +258,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht
 
     // Ionic Platform Grade is not A, disabling views transitions
     if (ionic.Platform.grade.toLowerCase() != 'a') {
-      console.log('[app] Disabling UI effects, because plateform\'s grade is [' + ionic.Platform.grade + ']');
+      console.info('[app] Disabling UI effects, because plateform\'s grade is [' + ionic.Platform.grade + ']');
       UIUtils.setEffects(false);
     }
 
diff --git a/www/js/components.js b/www/js/components.js
index b280578518bbf75c1ffc0fe310989936d13d6eea..34ba027d79a9ba0411352e67e436d18094f133d7 100644
--- a/www/js/components.js
+++ b/www/js/components.js
@@ -1,15 +1,5 @@
 angular.module('cesium')
 
-  .component('csAvatar', {
-    bindings: {
-      avatar: '<',
-      icon: '@'
-    },
-    template:
-    '<i ng-if="!$ctrl.avatar" class="item-image icon {{$ctrl.icon}}"></i>' +
-    '<i ng-if="$ctrl.avatar" class="item-image avatar" style="background-image: url({{::$ctrl.avatar.src}})"></i>'
-  })
-
   .component('csBadgeCertification', {
     bindings: {
       requirements: '=',
@@ -35,25 +25,8 @@ angular.module('cesium')
       toggle: '<'
     },
     template:
-    '<i class="ion-chevron-up" ng-class="{gray: !$ctrl.asc || $ctrl.sort != $ctrl.toggle}" style="position: relative;left : 5px; top:-5px; font-size: 9px;"></i>' +
+    '<i class="ion-chevron-up" ng-class="{gray: !$ctrl.asc || $ctrl.sort != $ctrl.toggle}" style="position: relative; left: 5px; top:-5px; font-size: 9px;"></i>' +
     '<i class="ion-chevron-down" ng-class="{gray : $ctrl.asc || $ctrl.sort != $ctrl.toggle}" style="position: relative; left: -2.6px; top: 3px; font-size: 9px;"></i>'
   })
 
-  .component('csRemovableSelectionItem', {
-    transclude: true,
-    controller: function(){
-      this.$onInit = function(){
-        console.log("$onInit called: ", this);
-      };
-      this.remove = function(){
-        console.log("remove called: ", this);
-      };
-    },
-    template:
-    '<div >' +
-    '  <ng-transclude></ng-transclude>' +
-    '  <i class="icon ion-close" ng-click="$ctrl.remove();"></i>' +
-    '</div>'
-  })
-
 ;
diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js
index 8604bd2c042a0fe2dd2e14709b4db8799eb1f8b7..bd968685f443b9fb994608ec3677cb608916f3a2 100644
--- a/www/js/controllers/app-controllers.js
+++ b/www/js/controllers/app-controllers.js
@@ -85,7 +85,7 @@ function PluginExtensionPointController($scope, PluginService) {
  */
 function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $timeout,
                        $ionicHistory, $controller, $window, csPlatform,
-                       UIUtils, BMA, csWallet, csCurrency, Device, Modals, csSettings, csConfig
+                       UIUtils, BMA, csWallet, Device, Modals, csConfig
   ) {
   'ngInject';
 
diff --git a/www/js/controllers/settings-controllers.js b/www/js/controllers/settings-controllers.js
index e1426513e8f9952b54c8d06d678cefde01a14fba..7e56d8f91c86513dbc06e12ecb59dc8d418b6a1a 100644
--- a/www/js/controllers/settings-controllers.js
+++ b/www/js/controllers/settings-controllers.js
@@ -113,7 +113,6 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t
   $scope.changeNode= function(node) {
     $scope.showNodePopup(node || $scope.formData.node)
     .then(function(newNode) {
-      console.log(newNode);
       if (newNode.host === $scope.formData.node.host &&
         newNode.port === $scope.formData.node.port &&
         newNode.useSsl === $scope.formData.node.useSsl) {
diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js
index a2c6b03ef18a07844c2869b5dde45b3618461dd2..ecc2d47e5070d977f84d702835ba1c55c2406dc6 100644
--- a/www/js/controllers/wallet-controllers.js
+++ b/www/js/controllers/wallet-controllers.js
@@ -521,22 +521,23 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state,
 }
 
 
-function WalletTxController($scope, $filter, $ionicPopover, $state, $timeout, UIUtils, csWallet,
-                            Modals, csSettings, BMA,csTx) {
+function WalletTxController($scope, $ionicPopover, $state, $timeout,
+                            UIUtils, Modals, BMA, csSettings, csWallet, csTx) {
   'ngInject';
 
   $scope.loading = true;
   $scope.settings = csSettings.data;
 
   $scope.$on('$ionicView.enter', function(e, state) {
-    if (!$scope.loading && (!state.stateParams || state.stateParams.refresh != 'true')) {
+    if (!$scope.loading && (!state.stateParams || !state.stateParams.refresh)) {
       // Make sure to display new pending (e.g. sending using another screen button)
-      $scope.updateView();
+      $timeout($scope.updateView, 300);
       return; // skip loading
     }
+
     $scope.loadWallet()
-      .then(function(walletData) {
-        $scope.formData = walletData;
+      .then(function(res) {
+        $scope.formData = res;
         $scope.loading=false; // very important, to avoid TX to be display before wallet.currentUd is loaded
         $scope.updateView();
         $scope.showFab('fab-transfer');
@@ -550,30 +551,14 @@ function WalletTxController($scope, $filter, $ionicPopover, $state, $timeout, UI
       });
   });
 
-  $scope.updateUnit = function() {
-    if (!$scope.formData || $scope.loading) return;
-    $scope.unit = $filter('currencySymbol')($scope.formData.currency, csSettings.data.useRelative);
-    $scope.secondaryUnit = $filter('currencySymbol')($scope.formData.currency, !csSettings.data.useRelative);
-  };
-
-  $scope.onSettingsChanged = function() {
-    $scope.updateUnit();
-  };
-  $scope.$watch('settings.useRelative', $scope.onSettingsChanged);
-
-  // Reload if show UD changed
-  $scope.$watch('settings.showUDHistory', function() {
-    if (!$scope.formData || $scope.loading) return;
-    $scope.doUpdate();
-  }, true);
 
   // Update view
   $scope.updateView = function() {
+    if (!$scope.formData || $scope.loading) return;
     $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
-    $scope.updateUnit();
-    $scope.motion.show({ink: false});
+    $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind
+    $scope.motion.show({selector: '.view-wallet-tx .item', ink: false});
   };
-  csWallet.api.data.on.balanceChanged($scope, $scope.updateView);
 
   $scope.downloadHistoryFile = function(options) {
     options = options || {};
@@ -592,6 +577,16 @@ function WalletTxController($scope, $filter, $ionicPopover, $state, $timeout, UI
       .catch(UIUtils.onError('ERROR.REFRESH_WALLET_DATA'));
   };
 
+  /* -- add listeners -- */
+
+  csWallet.api.data.on.balanceChanged($scope, $scope.updateView);
+  $scope.$watch('settings.useRelative', $scope.updateView);
+  $scope.$watch('settings.showUDHistory', function() {
+    // Reload if show UD changed
+    if (!$scope.formData || $scope.loading) return;
+      $scope.doUpdate();
+    }, true);
+
   /* -- popup / UI -- */
 
   // Transfer
@@ -624,7 +619,7 @@ function WalletTxController($scope, $filter, $ionicPopover, $state, $timeout, UI
         // If http rest limitation: wait then retry
         if (err.ucode == BMA.errorCodes.HTTP_LIMITATION) {
           $timeout(function() {
-            return $scope.showMoreTx();
+            return $scope.showMoreTx(fromTime);
           }, 2000);
         }
         else {
@@ -735,11 +730,9 @@ function WalletTxErrorController($scope, UIUtils, csWallet) {
   $scope.doUpdate = function() {
     UIUtils.loading.show();
     csWallet.refreshData()
-    .then(function() {
-      $scope.updateView();
-      UIUtils.loading.hide();
-    })
-    .catch(UIUtils.onError('ERROR.REFRESH_WALLET_DATA'));
+      .then(UIUtils.loading.hide)
+      .then($scope.doMotion)
+      .catch(UIUtils.onError('ERROR.REFRESH_WALLET_DATA'));
   };
 
   $scope.filterReceivedTx = function(tx){
@@ -978,7 +971,6 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate, Cr
       })
       .then(function(res) {
         if (!res) return;
-        console.log(res);
         var file = {
           file: _.filter($scope.formData.questions, function (question) {
             return question.checked;
diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js
index 172181ff9881294b365d1f40a021837c75f53ee2..167cba3b8eeb03630e91937e6f88851e1f4e1271 100644
--- a/www/js/controllers/wot-controllers.js
+++ b/www/js/controllers/wot-controllers.js
@@ -606,7 +606,6 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $
     // Need user auth - fix #513
     return csWallet.auth({minData: true})
       .then(function(walletData) {
-        console.log(walletData);
         UIUtils.loading.hide();
 
         if (!csCurrency.data.initPhase && !walletData.isMember) {
@@ -951,36 +950,56 @@ function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UI
 /**
  * Identity tx view controller
  */
-function WotIdentityTxViewController($scope, $timeout, csSettings, $controller, csTx, csWallet, BMA, UIUtils) {
+function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csCurrency, csWot, csTx, UIUtils) {
   'ngInject';
 
-  // Initialize the super class and extend it.
-  angular.extend(this, $controller('WotIdentityAbstractCtrl', {$scope: $scope}));
-
   $scope.formData= {};
   $scope.loading = true;
   $scope.motion = UIUtils.motion.fadeSlideInRight;
 
   $scope.$on('$ionicView.enter', function(e, state) {
+    if ($scope.loading) {
+      $scope.pubkey = state.stateParams.pubkey;
+      $scope.uid = state.stateParams.uid;
+      $scope.load();
+    }
+    else {
+      // update view
+      $scope.updateView();
+    }
+  });
 
-    $scope.pubkey= state.stateParams.pubkey;
-    $scope.uid= state.stateParams.uid;
-
-    // Load account TX data
-    csTx.load($scope.pubkey)
-      .then(function(result) {
-        if (result && result.tx && result.tx.history) {
-          $scope.tx = result.tx;
-          $scope.history = result.tx.history;
-        }
-        $scope.balance = result.balance;
-        $scope.load($scope.pubkey, true, $scope.uid)
-          .then(function(){
-            $scope.motion.show();
-            $scope.loading = false;
-          });
+  // Load data
+  $scope.load = function(fromTime) {
+    return $q.all([
+        csCurrency.get(),
+        csWot.extend({pubkey: $scope.pubkey}),
+        csTx.load($scope.pubkey, fromTime)
+      ])
+      .then(function(res) {
+        $scope.currency = res[0];
+        $scope.formData = angular.merge(res[1], res[2]);
+        $scope.loading = false;
+        $scope.updateView();
       });
-  });
+  };
+
+  // Updating data
+  $scope.doUpdate = function() {
+    console.debug('[wot] TX history reloading...');
+    return UIUtils.loading.show()
+      .then($scope.load)
+      .then(UIUtils.loading.hide)
+      .then($scope.updateView)
+      .catch(UIUtils.onError('ERROR.IDENTITY_TX_FAILED'));
+  };
+
+  // Update view
+  $scope.updateView = function() {
+    $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
+    $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind
+    $scope.motion.show();
+  };
 
   $scope.downloadHistoryFile = function(options) {
     options = options || {};
@@ -988,7 +1007,31 @@ function WotIdentityTxViewController($scope, $timeout, csSettings, $controller,
     csTx.downloadHistoryFile($scope.pubkey, options);
   };
 
-  //TODO : Manque l'actualisation des transactions + afficher plus/tout + bouton statistiques du compte
+  $scope.showMoreTx = function(fromTime) {
+
+    fromTime = fromTime ||
+      ($scope.formData.tx.fromTime - csSettings.data.walletHistoryTimeSecond) ||
+      (Math.trunc(new Date().getTime() / 1000) - 2 * csSettings.data.walletHistoryTimeSecond);
+
+    UIUtils.loading.show();
+    return csTx.load($scope.pubkey, fromTime)
+      .then(function(res) {
+        angular.merge($scope.formData, res);
+        $scope.updateView();
+        UIUtils.loading.hide();
+      })
+      .catch(function(err) {
+        // If http rest limitation: wait then retry
+        if (err.ucode == BMA.errorCodes.HTTP_LIMITATION) {
+          $timeout(function() {
+            return $scope.showMoreTx(fromTime);
+          }, 2000);
+        }
+        else {
+          UIUtils.onError('ERROR.IDENTITY_TX_FAILED')(err);
+        }
+      });
+  };
 
 }
 
diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js
index fb722339d2a3ba271626931c92639859b54a30b8..a04ffc2820d74017e414ba7678e55dc59963cab5 100644
--- a/www/js/services/bma-services.js
+++ b/www/js/services/bma-services.js
@@ -43,6 +43,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
         MEMBERSHIP_ALREADY_SEND: 2007,
         NO_CURRENT_BLOCK: 2010,
         BLOCK_NOT_FOUND: 2011,
+        SOURCE_ALREADY_CONSUMED: 2015,
         TX_INPUTS_OUTPUTS_NOT_EQUAL: 2024,
         TX_OUTPUT_SUM_NOT_EQUALS_PREV_DELTAS: 2025,
         TX_ALREADY_PROCESSED: 2030
@@ -684,8 +685,6 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
         if (exact(regexp.PUBKEY).test(uri)) {
           resolve({
             pubkey: uri
-
-
           });
         }
         else if(uri.startsWith('duniter://')) {
@@ -733,7 +732,6 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
                 });
               })
               .catch(function(err) {
-                console.log(err);
                 reject({message: 'Could not get node parameter. Currency could not be retrieve'});
               });
             }
diff --git a/www/js/services/crypto-services.js b/www/js/services/crypto-services.js
index c2f5a41a35535ac83f504ee073ba2b99e74d22f5..19833ed012bb07ccd93dd8ab59fbad40a8c2cf8f 100644
--- a/www/js/services/crypto-services.js
+++ b/www/js/services/crypto-services.js
@@ -444,10 +444,8 @@ angular.module('cesium.crypto.services', ['cesium.utils.services'])
         var naclOptions = {};
         var scryptOptions = {};
         if (ionic.Platform.grade.toLowerCase()!='a') {
-          console.log('Reduce NaCl memory because plateform grade is not [a] but [' + ionic.Platform.grade + ']');
+          console.info('Reduce NaCl memory because plateform grade is not [a] but [' + ionic.Platform.grade + ']');
           naclOptions.requested_total_memory = 16 * 1048576; // 16 Mo
-          console.log('Reduce Scrypt memory because plateform grade is not [a] but [' + ionic.Platform.grade + ']');
-          scryptOptions.requested_total_memory = 16 * 1048576; // 16 Mo
         }
         var loadedLib = 0;
         var checkAllLibLoaded = function() {
diff --git a/www/js/services/device-services.js b/www/js/services/device-services.js
index f4ea519633a63ca3dbabd584823117cf9b21100e..da81f75ecf0faa214f1518ad5c095d6515656bfa 100644
--- a/www/js/services/device-services.js
+++ b/www/js/services/device-services.js
@@ -123,7 +123,7 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti
       exports.camera = {
           getPicture : getPicture,
           scan: function(n){
-            console.log('Deprecated use of Device.camera.scan(). Use Device.barcode.scan() instead');
+            console.warn('Deprecated use of Device.camera.scan(). Use Device.barcode.scan() instead');
             return scan(n);
           }
         };
diff --git a/www/js/services/tx-services.js b/www/js/services/tx-services.js
index cd0a11be43437a298a867830b2bb58a480b0a737..59ccff35a677dd615b0e9641386e47e260ffc807 100644
--- a/www/js/services/tx-services.js
+++ b/www/js/services/tx-services.js
@@ -122,7 +122,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
         });
       },
 
-      loadTx = function(pubkey, fromTime, existingPendings) {
+      loadTx = function(pubkey, fromTime) {
         return $q(function(resolve, reject) {
           var txHistory = [];
           var udHistory = [];
@@ -138,7 +138,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
           var _reduceTx = function(res){
             _reduceTxAndPush(pubkey, res.history.sent, txHistory, processedTxMap);
             _reduceTxAndPush(pubkey, res.history.received, txHistory, processedTxMap);
-            _reduceTxAndPush(pubkey, res.history.sending, txHistory, processedTxMap);
+            _reduceTxAndPush(pubkey, res.history.sending, txPendings, processedTxMap, true /*allow pendings*/);
             _reduceTxAndPush(pubkey, res.history.pending, txPendings, processedTxMap, true /*allow pendings*/);
           };
 
diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js
index aefe3318c00b700f30a3ed065d6816d42a3a88dc..37c171b21729b98b5b455b09895a30932c6c9d72 100644
--- a/www/js/services/wallet-services.js
+++ b/www/js/services/wallet-services.js
@@ -21,7 +21,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
       IDTY_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION,
       MS_VERSION:   csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION,
       CERT_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION,
-      REVOKE_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION
+      REVOKE_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION,
+      TX_MAX_INPUTS_COUNT: 40 // Allow to get a TX with less than 100 rows (=max row count in Duniter protocol)
     },
     data = {},
     listeners,
@@ -524,6 +525,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
     loadTxAndSources = function(fromTime) {
       return csTx.load(data.pubkey, fromTime)
         .then(function(res){
+          resetTxAndSources();
           angular.merge(data, res);
         })
         .catch(function(err) {
@@ -936,8 +938,19 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
                 });
             })
             .catch(function(err) {
-              if (err && err.ucode === BMA.errorCodes.TX_INPUTS_OUTPUTS_NOT_EQUAL) {
-                // Send log message for debugging - issue #524 - https://github.com/duniter/cesium/issues/524
+
+              // Source already consumed: whould refresh wallet sources
+              if (err && err.ucode === BMA.errorCodes.SOURCE_ALREADY_CONSUMED) {
+                console.debug('[wallet] TX rejected by node with error [{0}]. Reloading sources then retry...'.format(err.message||'Source already consumed'));
+                return $timeout(loadTxAndSources, 500)
+                  .then(function() {
+                    return transfer(destPub, amount, comments, useRelative);
+                  });
+              }
+
+              // Error in generated TX - issue #524
+              else if (err && err.ucode === BMA.errorCodes.TX_INPUTS_OUTPUTS_NOT_EQUAL) {
+                // Ask user to send log to developers
                 var esEnable = csSettings.data.plugins && csSettings.data.plugins.es && csSettings.data.plugins.es.enable;
                 if (esEnable) {
                   UIUtils.loading.hide();
@@ -980,7 +993,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
 
       // Make sure a TX in compact mode has no more than 100 lines (fix #118)
       // (If more than 100 lines, send to TX to himself first, then its result as sources for the final TX)
-      if (inputs.sources.length > 40) {
+      if (inputs.sources.length > constants.TX_MAX_INPUTS_COUNT) {
         console.debug("[Wallet] TX has to many sources. Will chain TX...");
 
         // Compute a slice of sources
@@ -988,7 +1001,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
           minBase: block.unitbase,
           maxBase: 0,
           amount: 0,
-          sources: inputs.sources.slice(0, 39)
+          sources: inputs.sources.slice(0, constants.TX_MAX_INPUTS_COUNT) /* end index is excluded, so array length=TX_MAX_INPUTS_COUNT - issue #524 */
         };
         _.forEach(firstSlice.sources, function(source) {
           if (source.base < firstSlice.minBase) firstSlice.minBase = source.base;
@@ -1002,13 +1015,13 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
             _.forEach(firstSlice.sources, function(source) {
               source.consumed=true;
             });
-            data.sources.push(res.sources);
+            addSources(res.sources);
 
             var secondSlice = {
               minBase: block.unitbase,
               maxBase: 0,
               amount: 0,
-              sources: inputs.sources.slice(40).concat(res.sources)
+              sources: inputs.sources.slice(constants.TX_MAX_INPUTS_COUNT).concat(res.sources)
             };
             _.forEach(secondSlice.sources, function(source) {
               if (source.base < secondSlice.minBase) secondSlice.minBase = source.base;
diff --git a/www/plugins/es/js/controllers/group-controllers.js b/www/plugins/es/js/controllers/group-controllers.js
index 032500e4361c62ea59022e43e9deb82836022807..60cab476f7189580827f9c15b5cfb3eb4a707d79 100644
--- a/www/plugins/es/js/controllers/group-controllers.js
+++ b/www/plugins/es/js/controllers/group-controllers.js
@@ -55,11 +55,9 @@ angular.module('cesium.es.group.controllers', ['cesium.es.services'])
 
   .controller('ESGroupEditCtrl', ESGroupEditController)
 
-  .controller('PopoverGroupCtrl', PopoverGroupController)
-
 ;
 
-function ESGroupListController($scope, UIUtils, $state, BMA, csWallet, esGroup, ModalUtils) {
+function ESGroupListController($scope, UIUtils, $state, csWallet, esGroup, ModalUtils) {
   'ngInject';
 
   var defaultSearchLimit = 40;
@@ -179,122 +177,6 @@ function ESGroupListController($scope, UIUtils, $state, BMA, csWallet, esGroup,
   };
 }
 
-function PopoverGroupController($scope, $timeout, UIUtils, $state, csWallet, esNotification, esGroup, esModals) {
-  'ngInject';
-
-  var defaultSearchLimit = 40;
-
-  $scope.search = {
-    loading : true,
-    results: null,
-    hasMore : false,
-    loadingMore : false,
-    limit: defaultSearchLimit,
-    options: {
-      codes: {
-        includes: esNotification.constants.GROUP_CODES
-      }
-    }
-  };
-
-  $scope.load = function(from, size) {
-    var options = angular.copy($scope.search.options);
-    options.from = options.from || from || 0;
-    options.size = options.size || size || defaultSearchLimit;
-
-    return esNotification.load(csWallet.data.pubkey, options)
-      .then(function(notifications) {
-        if (!from) {
-          $scope.search.results = notifications;
-        }
-        else {
-          $scope.search.results = $scope.search.results.concat(notifications);
-        }
-        $scope.search.loading = false;
-        $scope.search.hasMore = ($scope.search.results && $scope.search.results.length >= $scope.search.limit);
-        $scope.updateView();
-      })
-      .catch(function(err) {
-        $scope.search.loading = false;
-        if (!from) {
-          $scope.search.results = [];
-        }
-        $scope.search.hasMore = false;
-        UIUtils.onError('MESSAGE.ERROR.LOAD_NOTIFICATIONS_FAILED')(err);
-      });
-  };
-
-  $scope.updateView = function() {
-
-    $timeout(function() {
-      UIUtils.ink({selector: '.popover-notification .item.ink'});
-    }, 100);
-  };
-
-  $scope.showMore = function() {
-    $scope.search.limit = $scope.search.limit || defaultSearchLimit;
-    $scope.search.limit = $scope.search.limit * 2;
-    if ($scope.search.limit < defaultSearchLimit) {
-      $scope.search.limit = defaultSearchLimit;
-    }
-    $scope.search.loadingMore = true;
-    $scope.load(
-      $scope.search.results.length, // from
-      $scope.search.limit)
-      .then(function() {
-        $scope.search.loadingMore = false;
-        $scope.$broadcast('scroll.infiniteScrollComplete');
-      });
-  };
-
-  $scope.onNewNotification = function(notification) {
-    if (!$scope.search.loading && !$scope.search.loadingMore &&  notification.isMessage) {
-      console.debug("[popover] detected new message (from notification service)");
-
-      if (notification.reference) {
-        console.log("[popover] new message has a reference !");
-      }
-      $scope.search.results.splice(0,0,notification);
-      $scope.updateView();
-    }
-  };
-
-  $scope.select = function(notification) {
-    if (!notification.read) notification.read = true;
-    $state.go('app.user_view_message', {id: notification.id});
-    $scope.closePopover(notification);
-  };
-
-  $scope.resetData = function() {
-    if ($scope.search.loading) return;
-    console.debug("[ES] [messages] Resetting data (settings or account may have changed)");
-    $scope.search.hasMore = false;
-    $scope.search.results = [];
-    $scope.search.loading = true;
-    delete $scope.search.limit;
-  };
-
-  csWallet.api.data.on.logout($scope, $scope.resetData);
-
-  /* -- Modals -- */
-
-  $scope.showNewMessageModal = function(parameters) {
-    $scope.closePopover();
-    return esModals.showMessageCompose(parameters)
-      .then(function(sent) {
-        if (sent) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT');
-      });
-  };
-
-  esNotification.api.data.on.new($scope, $scope.onNewNotification);
-
-  /* -- default popover action -- */
-  if ($scope.search.loading) {
-    $scope.load();
-  }
-
-}
-
 
 function ESGroupViewController($scope, $state, UIUtils, esGroup, csWallet) {
   'ngInject';
@@ -350,7 +232,7 @@ function ESGroupViewController($scope, $state, UIUtils, esGroup, csWallet) {
 }
 
 function ESGroupEditController($scope, esGroup, UIUtils, $state, $q, Device,
-                               $ionicHistory, ModalUtils, $focus, $timeout, esHttp) {
+                               $ionicHistory, ModalUtils, $focus, esHttp) {
   'ngInject';
 
   $scope.walletData = {};
diff --git a/www/plugins/es/js/services/social-services.js b/www/plugins/es/js/services/social-services.js
index ed1c385872cb8935d936be948496a50e0b2adc85..de204dee445652ba3f9fac7b72316b3a0e382b89 100644
--- a/www/plugins/es/js/services/social-services.js
+++ b/www/plugins/es/js/services/social-services.js
@@ -49,7 +49,7 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services'])
               urlToMatch = url.substring(0, slashPathIndex);
             }
           }
-          console.log("match URI, try to match: " + urlToMatch);
+          //console.debug("[social] match URI, try to match: " + urlToMatch);
           _.keys(regexp.socials).forEach(function(key){
             if (regexp.socials[key].test(urlToMatch)) {
               type = key;
@@ -63,9 +63,7 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services'])
         else if (regexp.EMAIL.test(url)) {
           type = 'email';
         }
-        if (!type) {
-            console.log("match type: " + type);
-        }
+        //if (!type) console.debug("[social] match type: " + type);
         return type;
       }
 
diff --git a/www/plugins/map/js/services/wot-services.js b/www/plugins/map/js/services/wot-services.js
index cffc91381ebae33dad6445f8c4704e7cd831f8b5..02aab8ad5292ccff59b512c95dd3034bc611d327 100644
--- a/www/plugins/map/js/services/wot-services.js
+++ b/www/plugins/map/js/services/wot-services.js
@@ -182,7 +182,7 @@ angular.module('cesium.map.wot.services', ['cesium.services'])
     // Resolve missing positions by addresses (only if google API enable)
     if (searchAddressItems.length) {
       var now = new Date().getTime();
-      console.log('[map] [wot] Search positions of {0} addresses...'.format(searchAddressItems.length));
+      console.debug('[map] [wot] Search positions of {0} addresses...'.format(searchAddressItems.length));
       var counter = 0;
 
       return $q.all(searchAddressItems.reduce(function(res, item) {
@@ -202,7 +202,7 @@ angular.module('cesium.map.wot.services', ['cesium.services'])
           .catch(function() {/*silent*/}));
       }, []))
         .then(function(){
-          console.log('[map] [wot] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, new Date().getTime()-now));
+          console.debug('[map] [wot] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, new Date().getTime()-now));
           return items;
         });
     }
diff --git a/www/templates/wallet/item_tx.html b/www/templates/wallet/item_tx.html
index c526814360255aaf41cfb1a020431ec00cd175eb..a9afffa13f13d35686e8a7cb12e6f1ed9b02accd 100644
--- a/www/templates/wallet/item_tx.html
+++ b/www/templates/wallet/item_tx.html
@@ -35,8 +35,7 @@
 
     <!-- not locked TX -->
     <span ng-if="::!tx.lockedOutputs" class="badge item-note" ng-class="{'badge-calm': tx.amount > 0}">
-      <span ng-bind-html=":rebind:tx.amount| formatAmount"></span>
-      <span ng-bind-html=":rebind:$root.currency.name|currencySymbol"></span>
+      <span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span>
     </span>
 
     <!-- Locked TX -->
@@ -45,14 +44,11 @@
        ng-class="{'badge-calm': tx.amount > 0}"
        ng-click="showLockedOutputsPopover(tx, $event)">
       <i class="icon ion-locked" ></i>
-      <span ng-bind-html=":rebind:tx.amount| formatAmount"></span>
-      <span ng-bind-html=":rebind:$root.currency.name|currencySymbol"></span>
+      <span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span>
     </a>
 
     <div class="badge badge-secondary" ng-if="$root.settings.expertMode">
-      (<ng-bind-html ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative}">
-    </ng-bind-html>
-      <span ng-bind-html=":rebind:secondaryUnit"></span>)
+      (<span ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}"></span>)
     </div>
   </div>
 </div>
diff --git a/www/templates/wallet/view_wallet_tx.html b/www/templates/wallet/view_wallet_tx.html
index e0346fe38f6c266581ca91aeb1025efd6b4fb030..e2ddba2218a648dd22c045d25699acaa45552de1 100644
--- a/www/templates/wallet/view_wallet_tx.html
+++ b/www/templates/wallet/view_wallet_tx.html
@@ -15,14 +15,11 @@
     <div class="positive-900-bg hero">
       <div class="content" ng-if="!loading">
         <h1 class="light">
-          <span ng-bind-html=":balance:rebind:formData.balance | formatAmount"></span>
-          <span ng-bind-html=":rebind:unit"></span>
-
+          <span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{currency: $root.currency.name}"></span>
         </h1>
         <h4 ng-if="!loading && $root.settings.expertMode"
                style="font-style: italic;">
-          (<span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{useRelative:!$root.settings.useRelative}"></span>
-          <span ng-bind-html=":rebind:secondaryUnit"></span>)
+          (<span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{useRelative:!$root.settings.useRelative, currency: $root.currency.name}"></span>)
         </h4>
         <div class="helptip-anchor-center">
           <a id="helptip-wallet-balance">&nbsp;</a>
diff --git a/www/templates/wallet/view_wallet_tx_error.html b/www/templates/wallet/view_wallet_tx_error.html
index 78e4eb481a197bc94656785041969200ec159d3a..b23a813b51a573577fbc543010f9010e16a42bd7 100644
--- a/www/templates/wallet/view_wallet_tx_error.html
+++ b/www/templates/wallet/view_wallet_tx_error.html
@@ -6,23 +6,20 @@
 
   <ion-nav-buttons side="secondary">
 
-    <button class="button button-icon button-clear icon ion-loop" ng-click="doUpdate()">
-    </button>
-    <button class="button button-icon button-clear" ng-click="actionsPopover.show($event)">
-      <i class="icon ion-android-more-vertical"></i>
+    <button class="button button-icon button-clear icon ion-loop visible-xs visible-sm " ng-click="doUpdate()">
     </button>
   </ion-nav-buttons>
 
   <ion-content scroll="true">
 
-    <!-- Buttons bar
-    <div class="hidden-xs hidden-sm padding" style="text-align:center"
-         ng-if="!!convertedBalance">
-      <button class="button button-raised button-energized-900 ink-dark"
-              ng-click="openTransfer()">
-        {{'ACCOUNT.BTN_SEND_MONEY' | translate}}
+    <!-- Buttons bar -->
+    <div class="hidden-xs hidden-sm padding text-center">
+
+      <button class="button button-stable button-small-padding icon ion-loop ink"
+              ng-click="doUpdate()"
+              title="{{'COMMON.BTN_REFRESH' | translate}}">
       </button>
-    </div>-->
+    </div>
 
     <div class="row no-padding">
       <div class="col col-20 hidden-xs hidden-sm">&nbsp;
@@ -44,7 +41,7 @@
         </span>
 
         <div class="item item-pending item-tx item-icon-left"
-             ng-repeat="tx in formData.tx.errors | filter: filterReceivedTx('amount')"
+             ng-repeat="tx in formData.tx.errors | filter: filterReceivedTx"
              ng-init="pending=true;"
              ng-include="'templates/wallet/item_tx.html'">
         </div>
@@ -63,7 +60,7 @@
         </span>
 
         <div class="item item-pending item-tx item-icon-left"
-             ng-repeat="tx in formData.tx.errors | filter: filterSentTx('amount')"
+             ng-repeat="tx in formData.tx.errors | filter: filterSentTx"
              ng-init="error=true;"
              ng-include="'templates/wallet/item_tx.html'">
         </div>
diff --git a/www/templates/wot/view_identity_tx.html b/www/templates/wot/view_identity_tx.html
index 44e61948c1e1dfb74678c764409bdd81fc299032..16499945901dc431bf23c02c4397a6937d0e7389 100644
--- a/www/templates/wot/view_identity_tx.html
+++ b/www/templates/wot/view_identity_tx.html
@@ -8,7 +8,7 @@
 
   <ion-content>
 
-    <div class="hidden-xs hidden-sm padding text-center" ng-if="!loading">
+    <div class="hidden-xs hidden-sm padding text-center">
 
       <button class="button button-stable button-small-padding icon ion-loop ink"
               ng-click="doUpdate()"
@@ -37,10 +37,12 @@
         <div class="col">
 
           <!-- the balance -->
-          <div class="item item-divider item-tx">
+          <div class="item item-tx item-divider">
             {{'ACCOUNT.BALANCE_ACCOUNT'|translate}}
-            <div class="badge badge-balanced">
-              {{balance|formatAmount}} <span ng-bind-html="$root.currency.name|currencySymbol"></span>
+            <div class="badge item-note badge-balanced" ng-bind-html=":balance:formData.balance|formatAmount:{currency: $root.currency.name}">
+            </div>
+            <div class="badge badge-secondary" ng-if="$root.settings.expertMode">
+              (<span ng-bind-html=":balance:formData.balance| formatAmount: {useRelative: !$root.settings.useRelative, currency: $root.currency.name} "></span>)
             </div>
           </div>
 
@@ -51,11 +53,11 @@
 
           <!-- iterate on each TX -->
           <div class="item item-tx item-icon-left"
-               ng-repeat="tx in history"
+               ng-repeat="tx in formData.tx.history"
                ng-include="'templates/wallet/item_tx.html'">
           </div>
 
-          <div class="item item-text-wrap text-center" ng-if="tx.fromTime > 0">
+          <div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0">
             <p>
               <a ng-click="showMoreTx()">{{:locale:'ACCOUNT.SHOW_MORE_TX'|translate}}</a>
               <span class="gray" translate="ACCOUNT.TX_FROM_DATE" translate-values="{fromTime: tx.fromTime}"></span>