diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js
index 8c19c2e9b83cef421fc88db6535970894ea19f2b..2ba2adb012cb62ae0adc7d2ac83664ed4f259f91 100644
--- a/www/js/services/bma-services.js
+++ b/www/js/services/bma-services.js
@@ -246,7 +246,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
           if (software === 'duniter' && json.duniter.version && true) {
             isCompatible = csHttp.version.isCompatible(csSettings.data.minVersion, json.duniter.version);
           }
-          // TODO: check other software (DURS, Juniter, etc.)
+          // TODO: check version of other software (DURS, Juniter, etc.)
           else {
             console.debug('[BMA] Unknown node software [{0} v{1}]: could not check compatibility.'.format(software || '?', json.duniter.version || '?'));
           }
@@ -424,8 +424,8 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
         },
         requirements: function(params, withCache) {
           // No cache by default
-          if (withCache !== true) return exports.raw.requirementsNoCache(params);
-          return exports.raw.requirementsWithCache(params);
+          if (withCache !== true) return exports.raw.wot.requirements(params);
+          return exports.raw.wot.requirementsWithCache(params);
         },
         add: post('/wot/add'),
         certify: post('/wot/certify'),
@@ -449,9 +449,27 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
         sources: get('/tx/sources/:pubkey', csHttp.cache.SHORT),
         process: post('/tx/process'),
         history: {
-          all: get('/tx/history/:pubkey'),
-          times: get('/tx/history/:pubkey/times/:from/:to', csHttp.cache.LONG),
-          timesNoCache: get('/tx/history/:pubkey/times/:from/:to'),
+          all: function(params) {
+            return exports.raw.tx.history.all(params)
+              .then(res => {
+                res.history = res.history || {};
+                // Clean sending and pendings, because already returned by tx/history/:pubkey/pending
+                res.history.sending = [];
+                res.history.pendings = [];
+                return res;
+              });
+          },
+          times: function(params, withCache) {
+            // No cache by default
+            return ((withCache !== true) ? exports.raw.tx.history.times(params) : exports.raw.tx.history.timesWithCache(params))
+              .then(res => {
+                res.history = res.history || {};
+                // Clean sending and pendings, because already returned by tx/history/:pubkey/pending
+                res.history.sending = [];
+                res.history.pendings = [];
+                return res;
+              });
+          },
           blocks: get('/tx/history/:pubkey/blocks/:from/:to', csHttp.cache.LONG),
           pending: get('/tx/history/:pubkey/pending')
         }
@@ -462,11 +480,19 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
       uri: {},
       version: {},
       raw: {
-        requirementsWithCache: get('/wot/requirements/:pubkey', csHttp.cache.LONG),
-        requirementsNoCache: get('/wot/requirements/:pubkey')
+        wot: {
+          requirementsWithCache: get('/wot/requirements/:pubkey', csHttp.cache.LONG),
+          requirements: get('/wot/requirements/:pubkey')
+        },
+        tx: {
+          history: {
+            timesWithCache: get('/tx/history/:pubkey/times/:from/:to', csHttp.cache.LONG),
+            times: get('/tx/history/:pubkey/times/:from/:to'),
+            all: get('/tx/history/:pubkey')
+          }
+        },
       }
     };
-    exports.regex = exports.regexp; // deprecated
 
     exports.tx.parseUnlockCondition = function(unlockCondition) {
 
@@ -917,7 +943,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
       csHttp.getWithCache(duniterLatestReleaseUrl.host,
         duniterLatestReleaseUrl.port,
         "/" + duniterLatestReleaseUrl.pathname,
-        /*useSsl*/ (duniterLatestReleaseUrl.port == 443 || duniterLatestReleaseUrl.protocol == 'https:' || that.forceUseSsl),
+        /*useSsl*/ (+(duniterLatestReleaseUrl.port) === 443 || duniterLatestReleaseUrl.protocol === 'https:' || that.forceUseSsl),
         csHttp.cache.LONG
       ) :
       // No URL define: use a fake function
diff --git a/www/js/services/cache-services.js b/www/js/services/cache-services.js
index 08921d8bde5ee4a73c84d8de86867979821bb5cd..a1e4f8aaa0010de22a40acdaccdf5ae9b2aa3ecc 100644
--- a/www/js/services/cache-services.js
+++ b/www/js/services/cache-services.js
@@ -16,9 +16,9 @@ angular.module('cesium.cache.services', ['angular-cache'])
   function getOrCreateCache(prefix, maxAge, onExpire){
     prefix = prefix || 'csCache-';
     maxAge = maxAge || constants.SHORT;
-    var cacheName = prefix + maxAge;
+    var cacheName = prefix + (maxAge / 1000);
 
-    // FIXME : enable this when cache is cleaning on rollback
+    // FIXME: enable this when cache is cleaning on rollback
     var storageMode = csSettings.data.useLocalStorage && $window.localStorage ? 'localStorage' : 'memory';
 
     if (!onExpire) {
diff --git a/www/js/services/currency-services.js b/www/js/services/currency-services.js
index 1b3888305fd6b32a1b1736953a21d25ecefb5acc..4caaacf82eec57b669d880592974bdd9f941c5d3 100644
--- a/www/js/services/currency-services.js
+++ b/www/js/services/currency-services.js
@@ -268,7 +268,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services'])
           var now = moment().utc().unix();
 
           if (cache) {
-            if (currentBlock && (now - currentBlock.receivedAt) < 60/*1min*/) {
+            if (currentBlock && currentBlock.receivedAt && (now - currentBlock.receivedAt) < 60/*1min*/) {
               //console.debug('[currency] Use current block #'+ currentBlock.number +' from cache (age='+ (now - currentBlock.receivedAt) + 's)');
               return currentBlock;
             }
@@ -283,7 +283,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services'])
             .catch(function(err){
               // Special case for currency init (root block not exists): use fixed values
               if (err && err.ucode == BMA.errorCodes.NO_CURRENT_BLOCK) {
-                return {number: 0, hash: BMA.constants.ROOT_BLOCK_HASH, medianTime: moment().utc().unix()};
+                return {number: 0, hash: BMA.constants.ROOT_BLOCK_HASH, medianTime: now};
               }
               throw err;
             })
diff --git a/www/js/services/settings-services.js b/www/js/services/settings-services.js
index 6ac96e2e07b87f77af1f20544f489b389d96de89..c4d03f90960e3ab27161b5c89b2976acfd35122c 100644
--- a/www/js/services/settings-services.js
+++ b/www/js/services/settings-services.js
@@ -1,7 +1,7 @@
 
 angular.module('cesium.settings.services', ['ngApi', 'cesium.config'])
 
-.factory('csSettings', function($rootScope, $q, Api, localStorage, $translate, csConfig) {
+.factory('csSettings', function($rootScope, $q, $window, Api, localStorage, $translate, csConfig) {
   'ngInject';
 
   // Define app locales
@@ -41,7 +41,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config'])
   // Convert browser locale to app locale (fix #140)
   function fixLocaleWithLog (locale) {
     var fixedLocale = fixLocale(locale);
-    if (locale != fixedLocale) {
+    if (locale !== fixedLocale) {
       console.debug('[settings] Fix locale [{0}] -> [{1}]'.format(locale, fixedLocale));
     }
     return fixedLocale;
@@ -67,7 +67,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config'])
   },
   defaultSettings = angular.merge({
     useRelative: false,
-    useLocalStorage: true, // override to false if no device
+    useLocalStorage: !!$window.localStorage, // override to false if no device
     useLocalStorageEncryption: false,
     walletHistoryTimeSecond: 30 * 24 * 60 * 60 /*30 days*/,
     walletHistorySliceSecond: 5 * 24 * 60 * 60 /*download using 5 days slice*/,
diff --git a/www/js/services/tx-services.js b/www/js/services/tx-services.js
index 2572c44b2df78496f7acd51089fa345f278596ee..ff37081adef1ab624cca5182b06d55fda1ce2878 100644
--- a/www/js/services/tx-services.js
+++ b/www/js/services/tx-services.js
@@ -18,7 +18,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
         if (!txArray || !txArray.length) return; // Skip if empty
 
         _.forEach(txArray, function(tx) {
-          if (tx.block_number || allowPendings) {
+          if (tx.block_number !== null || allowPendings) {
             var walletIsIssuer = false;
             var otherIssuer = tx.issuers.reduce(function(issuer, res) {
               walletIsIssuer = walletIsIssuer || (res === pubkey);
@@ -30,7 +30,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
             var otherReceiver;
             var outputBase;
             var sources = [];
-            var lockedOutputs;
+            let lockedOutputs;
             var amount = tx.outputs.reduce(function(sum, output, noffset) {
               // FIXME duniter v1.4.13
               var outputArray = (typeof output == 'string') ? output.split(':',3) : [output.amount,output.base,output.conditions];
@@ -42,7 +42,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
               // Simple unlock condition
               if (sigMatches) {
                 var outputPubkey = sigMatches[1];
-                if (outputPubkey == pubkey) { // output is for the wallet
+                if (outputPubkey === pubkey) { // output is for the wallet
                   if (!walletIsIssuer) {
                     return sum + outputAmount;
                   }
@@ -54,7 +54,8 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
                       type: 'T',
                       identifier: tx.hash,
                       noffset: noffset,
-                      consumed: false
+                      consumed: false,
+                      conditions: outputCondition
                     });
                   }
                 }
@@ -69,20 +70,19 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
               }
 
               // Complex unlock condition, on the issuer pubkey
-              else if (outputCondition.indexOf('SIG('+pubkey+')') != -1) {
+              else if (outputCondition.indexOf('SIG('+pubkey+')') !== -1) {
                 var lockedOutput = BMA.tx.parseUnlockCondition(outputCondition);
                 if (lockedOutput) {
                   // Add a source
-                  // FIXME: should be uncomment when filtering source on transfer()
-                  /*sources.push(angular.merge({
+                  sources.push(angular.merge({
                    amount: parseInt(outputArray[0]),
                    base: outputBase,
                    type: 'T',
                    identifier: tx.hash,
                    noffset: noffset,
+                   conditions: outputCondition,
                    consumed: false
                    }, lockedOutput));
-                   */
                   lockedOutput.amount = outputAmount;
                   lockedOutputs = lockedOutputs || [];
                   lockedOutputs.push(lockedOutput);
@@ -99,8 +99,8 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
 
             // Avoid duplicated tx, or tx to him self
             var txKey = amount + ':' + tx.hash + ':' + time;
-            if (!processedTxMap[txKey] && amount !== 0) {
-              processedTxMap[txKey] = true;
+            if (!processedTxMap[txKey]) {
+              processedTxMap[txKey] = true; // Mark as processed
               var newTx = {
                 time: time,
                 amount: amount,
@@ -137,10 +137,8 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
             errors: []
           };
 
-          var processedTxMap = {};
-          var _reduceTx = function (res) {
-            _reduceTxAndPush(pubkey, res.history.sent, tx.history, processedTxMap);
-            _reduceTxAndPush(pubkey, res.history.received, tx.history, processedTxMap);
+          const processedTxMap = {};
+          const _reducePendingTx = function (res) {
             _reduceTxAndPush(pubkey, res.history.sending, tx.pendings, processedTxMap, true /*allow pendings*/);
             _reduceTxAndPush(pubkey, res.history.pending, tx.pendings, processedTxMap, true /*allow pendings*/);
           };
@@ -151,24 +149,29 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
 
             // get pending tx
             BMA.tx.history.pending({pubkey: pubkey})
-              .then(_reduceTx)
+              .then(_reducePendingTx)
           ];
 
           // get TX history since
           if (fromTime !== 'pending') {
+            const _reduceTx = function (res) {
+              _reduceTxAndPush(pubkey, res.history.sent, tx.history, processedTxMap, false);
+              _reduceTxAndPush(pubkey, res.history.received, tx.history, processedTxMap, false);
+            };
 
             // get TX from a given time
             if (fromTime > 0) {
               // Use slice, to be able to cache requests result
-              var sliceTime = csSettings.data.walletHistorySliceSecond;
+              const sliceTime = csSettings.data.walletHistorySliceSecond;
               fromTime = fromTime - (fromTime % sliceTime);
               for(var i = fromTime; i - sliceTime < nowInSec; i += sliceTime)  {
-                jobs.push(BMA.tx.history.times({pubkey: pubkey, from: i, to: i+sliceTime-1})
+                jobs.push(BMA.tx.history.times({pubkey: pubkey, from: i, to: i+sliceTime-1}, true /*with cache*/)
                   .then(_reduceTx)
                 );
               }
 
-              jobs.push(BMA.tx.history.timesNoCache({pubkey: pubkey, from: nowInSec - (nowInSec % sliceTime), to: nowInSec+999999999})
+              // Last slide: no cache
+              jobs.push(BMA.tx.history.times({pubkey: pubkey, from: nowInSec - (nowInSec % sliceTime), to: nowInSec+999999999}, false/*no cache*/)
                 .then(_reduceTx));
             }
 
@@ -226,13 +229,11 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
               tx.history.sort(function(tx1, tx2) {
                 return (tx2.time - tx1.time);
               });
-              tx.validating = tx.history.filter(function(tx) {
-                return (tx.block_number > current.number - csSettings.data.blockValidityWindow);
+              const firstValidatedTxIndex = tx.history.findIndex((tx) => {
+                return (tx.block_number <= current.number - csSettings.data.blockValidityWindow);
               });
               // remove validating from history
-              if (tx.validating.length) {
-                tx.history.splice(0, tx.validating.length);
-              }
+              tx.validating = firstValidatedTxIndex > 0 ? tx.history.splice(0, firstValidatedTxIndex) : [];
 
               tx.fromTime = fromTime !== 'pending' && fromTime || undefined;
               tx.toTime = tx.history.length ? tx.history[0].time /*=max(tx.time)*/: tx.fromTime;
@@ -314,7 +315,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
                 // TODO get sources from the issuer ?
               }
               else {
-                _.forEach(tx.inputs, function(input) {
+                _.find(tx.inputs, function(input) {
                   var inputKey = input.split(':').slice(2).join(':');
                   var srcIndex = data.sourcesIndexByKey[inputKey];
                   if (angular.isDefined(srcIndex)) {
@@ -322,7 +323,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
                   }
                   else {
                     valid = false;
-                    return false; // break
+                    return true; // break
                   }
                 });
                 if (tx.sources) { // add source output
@@ -377,6 +378,10 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
                 console.debug('[tx] TX and sources loaded in '+ (Date.now()-now) +'ms');
                 return data;
               });
+          })
+          .catch(function(err) {
+            console.warn("[tx] Error while getting sources and tx...", err);
+            throw err;
           });
     },
 
diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js
index 5477306815f9bc1dd31b1aff27b77ac9c353b528..174ec9f68590fbae1d5953464f7a98e7b2694afa 100644
--- a/www/js/services/wallet-services.js
+++ b/www/js/services/wallet-services.js
@@ -120,6 +120,9 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
     addSource = function(src, sources, sourcesIndexByKey) {
       var srcKey = src.type+':'+src.identifier+':'+src.noffset;
       if (angular.isUndefined(sourcesIndexByKey[srcKey])) {
+        if (!src.conditions) {
+          console.warn("Trying to add a source without output condition !", src);
+        }
         sources.push(src);
         sourcesIndexByKey[srcKey] = sources.length - 1;
       }
@@ -341,7 +344,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
       if (options) {
         if (options.minData && !options.sources) return data.loaded && true;
         if (options.requirements && !data.requirements.loaded) return false;
-        if (options.tx && options.tx.enable && (!data.tx.fromTime || data.tx.fromTime == 'pending')) return false;
+        if (options.tx && options.tx.enable && (!data.tx.fromTime || data.tx.fromTime === 'pending')) return false;
         if (options.sigStock && !data.sigStock) return false;
       }
       return data.loaded && data.sources && true;
@@ -357,14 +360,18 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
          !data.requirements.needSelf ||
          data.requirements.wasMember ||
 
+         // Check sources
+        (data.sources && data.sources.length > 0) ||
+
          // Check TX history
-         data.tx.history.length ||
-         data.tx.pendings.length ||
+         data.tx.history.length > 0 ||
+         data.tx.validating.length > 0 ||
+         data.tx.pendings.length > 0 ||
 
          // Check extended data (name+avatar)
-         data.localName ||
-         data.name ||
-         data.avatar
+         !!data.localName ||
+         !!data.name ||
+         !!data.avatar
         );
     },
 
@@ -851,7 +858,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
         // Warn if wallet has been never used - see #167
         .then(function() {
           var unused = isNeverUsed();
-          var showAlert = alertIfUnusedWallet && !isNew() && angular.isDefined(unused) && unused;
+          var showAlert = alertIfUnusedWallet && !isNew() && unused === true;
           if (!showAlert) return true;
           return UIUtils.loading.hide()
             .then(function() {
@@ -890,7 +897,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
         });
     },
 
-    loadFullData = function() {
+    loadFullData = function(fromTime) {
       data.loaded = false;
 
       return $q.all([
@@ -907,8 +914,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
               }
             }),
 
-          // Get TX and sources
-          loadTxAndSources()
+          // Get TX and sources (only pending by default)
+          loadTxAndSources(fromTime || 'pending')
         ])
         .then(function() {
 
@@ -951,7 +958,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
           sources: true,
           tx: {
             enable: true,
-            fromTime: data.tx ? data.tx.fromTime : undefined // keep previous time
+            fromTime: data.tx && data.tx.fromTime !== 'pending' ? data.tx.fromTime : undefined // keep previous time
           },
           sigStock: true,
           api: true
@@ -986,8 +993,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
       }
 
       else if (options.sources && (options.tx && !options.tx.enable)) {
-        // Get sources (no TX)
-        jobs.push(loadSources());
+        // Get sources and only pending TX (and NOT the TX history)
+        jobs.push(loadTxAndSources('pending'));
       }
 
       // Load sigStock
@@ -1425,7 +1432,9 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
               type: 'T',
               noffset: outputOffset,
               amount: outputAmount,
-              base: outputBase
+              base: outputBase,
+              conditions: 'SIG('+restPub+')',
+              consumed: false
             });
           }
           outputOffset++;