From 42d27215809a0a542426b82f859c0f62eafc534a Mon Sep 17 00:00:00 2001
From: Benoit Lavenier <benoit.lavenier@e-is.pro>
Date: Fri, 20 Dec 2019 19:31:01 +0100
Subject: [PATCH] [enh] Allow to switch between secondary wallets more easily
 [enh] Allow to see message of secondary wallets [fix] Fix crypto error for
 use of js-nacl [fix] Wot identity: Adapt hero header when QRcode is zoom

---
 www/js/config.js                              |  56 +-
 www/js/controllers/blockchain-controllers.js  |   4 +-
 www/js/controllers/currency-controllers.js    |   2 +-
 www/js/controllers/network-controllers.js     |  12 +-
 www/js/controllers/wallet-controllers.js      |  27 +-
 www/js/controllers/wallets-controllers.js     | 696 +++++++++---------
 www/js/controllers/wot-controllers.js         |   4 +-
 www/js/services/crypto-services.js            |  94 ++-
 www/js/services/modal-services.js             |  49 +-
 www/js/services/utils-services.js             |   7 +-
 www/js/services/wallet-services.js            |   2 +-
 .../es/js/controllers/app-controllers.js      |   2 +-
 .../es/js/controllers/document-controllers.js |   2 +-
 .../es/js/controllers/message-controllers.js  | 275 ++++---
 .../es/js/controllers/profile-controllers.js  |   6 +-
 .../es/js/controllers/registry-controllers.js |   4 +-
 .../controllers/subscription-controllers.js   |  18 +-
 .../es/js/controllers/wot-controllers.js      |   2 +-
 .../es/js/services/comment-services.js        |   7 +-
 .../es/js/services/document-services.js       |  14 +-
 www/plugins/es/js/services/http-services.js   |  30 +-
 .../es/js/services/invitation-services.js     |  51 +-
 .../es/js/services/message-services.js        | 103 ++-
 .../es/js/services/subscription-services.js   |   8 +-
 www/plugins/es/templates/message/list.html    |   4 +-
 .../es/templates/message/lookup_by_id.html    |  17 +
 .../es/templates/message/lookup_lg.html       |  34 +-
 .../es/templates/message/popover_message.html |   2 +-
 .../wallet/list/item_wallet_light.html        |   2 +-
 .../wallet/list/popover_wallets.html          |  32 +-
 www/templates/wallet/list/view_wallets.html   |   3 +
 www/templates/wallet/view_wallet.html         |  21 +-
 www/templates/wot/view_identity.html          |   2 +-
 33 files changed, 912 insertions(+), 680 deletions(-)
 create mode 100644 www/plugins/es/templates/message/lookup_by_id.html

diff --git a/www/js/config.js b/www/js/config.js
index de9aeab2e..166c63d8e 100644
--- a/www/js/config.js
+++ b/www/js/config.js
@@ -12,78 +12,38 @@ angular.module("cesium.config", [])
 	"cacheTimeMs": 300000,
 	"fallbackLanguage": "en",
 	"rememberMe": true,
-	"showUDHistory": true,
-	"timeout": 40000,
+	"timeout": 300000,
 	"timeWarningExpireMembership": 5184000,
 	"timeWarningExpire": 7776000,
-	"keepAuthIdle": 600,
 	"useLocalStorage": true,
 	"useRelative": false,
-	"expertMode": false,
+	"expertMode": true,
 	"decimalCount": 2,
-	"httpsMode": false,
 	"shareBaseUrl": "https://g1.duniter.fr",
 	"helptip": {
-		"enable": true,
+		"enable": false,
 		"installDocUrl": {
 			"fr-FR": "https://duniter.org/fr/wiki/duniter/installer/",
-			"en": "https://duniter.org/en/wiki/duniter/install/"
+			"en": "https://github.com/duniter/duniter/blob/master/doc/install-a-node.md"
 		}
 	},
-	"license": {
-		"en": "license/license_g1-en",
-		"fr-FR": "license/license_g1-fr-FR",
-		"es-ES": "license/license_g1-es-ES"
-	},
 	"node": {
-		"host": "g1.duniter.org",
+		"host": "g1-test.duniter.org",
 		"port": 443
 	},
 	"fallbackNodes": [
 		{
-			"host": "g1.nordstrom.duniter.org",
-			"port": 443
-		},
-		{
-			"host": "g1.cgeek.fr",
-			"port": 443
-		},
-		{
-			"host": "g1.monnaielibreoccitanie.org",
-			"port": 443
-		},
-		{
-			"host": "g1.le-sou.org",
-			"port": 443
-		},
-		{
-			"host": "g1.duniter.fr",
+			"host": "g1-test.cgeek.fr",
 			"port": 443
 		}
 	],
-	"developers": [
-		{
-			"name": "Benoit Lavenier",
-			"pubkey": "38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE"
-		}
-	],
 	"plugins": {
 		"es": {
 			"enable": true,
 			"askEnable": true,
 			"useRemoteStorage": true,
-			"host": "g1.data.duniter.fr",
+			"host": "g1-test.data.duniter.fr",
 			"port": 443,
-			"fallbackNodes": [
-				{
-					"host": "g1.data.le-sou.org",
-					"port": 443
-				},
-				{
-					"host": "g1.data.duniter.fr",
-					"port": 443
-				}
-			],
 			"notifications": {
 				"txSent": true,
 				"txReceived": true,
@@ -94,7 +54,7 @@ angular.module("cesium.config", [])
 		}
 	},
 	"version": "1.4.12",
-	"build": "2019-11-16T13:39:37.358Z",
+	"build": "2019-12-19T14:53:37.759Z",
 	"newIssueUrl": "https://git.duniter.org/clients/cesium-grp/cesium/issues/new"
 })
 
diff --git a/www/js/controllers/blockchain-controllers.js b/www/js/controllers/blockchain-controllers.js
index 983f762ca..efd8e141c 100644
--- a/www/js/controllers/blockchain-controllers.js
+++ b/www/js/controllers/blockchain-controllers.js
@@ -331,12 +331,12 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
 
     $scope.smallscreen = UIUtils.screen.isSmall();
 
+    $scope.$broadcast('$$rebind::rebind'); // notify binder
+
     // Set Motion
     if (res && res.length) {
       $scope.motion.show({selector: '.list-blocks .item-block'});
     }
-
-    $scope.$broadcast('$$rebind::rebind'); // notify binder
   };
 
   $scope.showMore = function() {
diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js
index 30467cb70..985276bed 100644
--- a/www/js/controllers/currency-controllers.js
+++ b/www/js/controllers/currency-controllers.js
@@ -235,7 +235,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA
 
       console.debug("[currency] Parameters loaded in " + (Date.now() - now) + 'ms' );
       $scope.loading = false;
-      $scope.$broadcast('$$rebind::' + 'rebind'); // force bind of currency name
+      $scope.$broadcast('$$rebind::rebind'); // force bind of currency name
 
       // Set Ink
       UIUtils.ink();
diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js
index bfeb74bbf..0fdbb64ea 100644
--- a/www/js/controllers/network-controllers.js
+++ b/www/js/controllers/network-controllers.js
@@ -179,17 +179,17 @@ function NetworkLookupController($scope,  $state, $location, $ionicPopover, $win
 
   $scope.updateView = function(data) {
     console.debug("[peers] Updating UI");
-    $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding
+    $scope.$broadcast('$$rebind::rebind'); // force data binding
     $scope.search.results = data.peers;
     $scope.search.memberPeersCount = data.memberPeersCount;
     // Always tru if network not started (e.g. after leave+renter the view)
     $scope.search.loading = !$scope.networkStarted || csNetwork.isBusy();
+    if (!$scope.loading) {
+      $scope.$broadcast('$$rebind::rebind'); // force data binding
+    }
     if ($scope.motion && $scope.search.results && $scope.search.results.length > 0) {
       $scope.motion.show({selector: '.item-peer'});
     }
-    if (!$scope.loading) {
-      $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding
-    }
   };
 
   $scope.refresh = function() {
@@ -248,7 +248,7 @@ function NetworkLookupController($scope,  $state, $location, $ionicPopover, $win
 
   $scope.toggleCompactMode = function() {
     $scope.compactMode = !$scope.compactMode;
-    $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding
+    $scope.$broadcast('$$rebind::rebind'); // force data binding
   };
 
   $scope.selectPeer = function(peer) {
@@ -506,7 +506,7 @@ function PeerInfoPopoverController($scope, $q, csSettings, csCurrency, csHttp, B
           $scope.formData.hasNewRelease = false;
         }
         $scope.loading = false;
-        $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding
+        $scope.$broadcast('$$rebind::rebind'); // force data binding
       });
   };
 
diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js
index 5fe49a977..920a25f9f 100644
--- a/www/js/controllers/wallet-controllers.js
+++ b/www/js/controllers/wallet-controllers.js
@@ -114,7 +114,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state,
 
   $scope.updateView = function() {
     $scope.motion.show({selector: '#wallet .item'});
-    $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind
+    $scope.$broadcast('$$rebind::rebind'); // force rebind
   };
 
 
@@ -558,7 +558,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state,
       .then(function(done){
         if (done) {
           UIUtils.toast.show('INFO.TRANSFER_SENT');
-          $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
+          $scope.$broadcast('$$rebind::balance'); // force rebind balance
           $scope.motion.show({selector: '.item-pending'});
         }
       });
@@ -645,11 +645,13 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state,
   };
 
   $scope.showSelectWalletPopover = function(event) {
+
     return csPopovers.showSelectWallet(event, {
-        scope: $scope
-      })
+      parameters: {
+        excludedWalletId: $scope.walletId
+      }})
       .then(function(newWallet) {
-        if (!newWallet || newWallet.id === wallet.id) return;
+        if (!newWallet || newWallet.id === $scope.walletId) return; // nothing changed
         if (newWallet.isDefault()) {
           return $state.go('app.view_wallet');
         }
@@ -692,6 +694,8 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location,
         return $scope.showHome();
       }
 
+      $scope.walletId = wallet.id;
+
       $scope.cleanLocationHref(state);
 
       return $scope.load();
@@ -754,8 +758,8 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location,
   // Update view
   $scope.updateView = function() {
     if (!$scope.formData || $scope.loading) return;
-    $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
-    $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind
+    $scope.$broadcast('$$rebind::balance'); // force rebind balance
+    $scope.$broadcast('$$rebind::rebind'); // force rebind
     $scope.motion.show({selector: '.view-wallet-tx .item', ink: false});
   };
 
@@ -841,7 +845,7 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location,
       .then(function(done){
         if (done) {
           UIUtils.toast.show('INFO.TRANSFER_SENT');
-          $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
+          $scope.$broadcast('$$rebind::balance'); // force rebind balance
           $scope.motion.show({selector: '.item-pending'});
         }
       });
@@ -887,8 +891,11 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location,
     if (!csWallet.children.count()) return;
 
     return Modals.showSelectWallet({
-      showDefault: true,
-      showBalance: false
+      parameters: {
+        showDefault: true,
+        showBalance: false,
+        excludedWalletId: $scope.walletId
+      }
     })
     .then(function(newWallet) {
       if (!newWallet || wallet && newWallet.id === wallet.id) return;
diff --git a/www/js/controllers/wallets-controllers.js b/www/js/controllers/wallets-controllers.js
index 5d399f787..2731fcfa5 100644
--- a/www/js/controllers/wallets-controllers.js
+++ b/www/js/controllers/wallets-controllers.js
@@ -9,7 +9,7 @@ angular.module('cesium.wallets.controllers', ['cesium.services', 'cesium.currenc
         views: {
           'menuContent': {
             templateUrl: "templates/wallet/list/view_wallets.html",
-            controller: 'WalletListCtrl'
+            controller: 'WalletListViewCtrl'
           }
         },
         data: {
@@ -59,119 +59,220 @@ angular.module('cesium.wallets.controllers', ['cesium.services', 'cesium.currenc
       })
     ;
   })
+  .controller('WalletListAbstractCtrl', WalletListAbstractController)
 
-
-  .controller('WalletListCtrl', WalletListController)
+  .controller('WalletListViewCtrl', WalletListViewController)
 
   .controller('WalletSelectModalCtrl', WalletSelectModalController)
 
   .controller('WalletListImportModalCtrl', WalletListImportModalController)
 
-  .controller('PopoverWalletSelectModalCtrl', PopoverWalletSelectModalController)
+  .controller('WalletSelectPopoverCtrl', WalletSelectPopoverController)
 ;
 
-function WalletListController($scope, $controller, $state, $timeout, $q, $translate, $ionicPopover, $ionicPopup,
-                              ModalUtils, UIUtils, Modals, csCurrency, csSettings, csWallet){
+
+function WalletListAbstractController($scope, $q, $timeout, UIUtils, filterTranslations, csSettings, csCurrency, csWallet) {
   'ngInject';
 
-  $scope.settings = csSettings.data;
-  $scope.listeners = [];
+  $scope.loading = true;
+  $scope.wallets = null;
+  $scope.formData = {
+    useRelative: csSettings.data.useRelative,
+    showDefault: true,
+    showBalance: false,
+    balance: undefined,
+    updatingWalletId: undefined,
+    stopped: false,
+    minData: true
+  };
+  $scope.motion = null; // no animation
 
-  // Initialize the super class and extend it.
-  angular.extend(this, $controller('WalletSelectModalCtrl', {$scope: $scope, parameters: {}}));
+  $scope.setParameters = function(parameters) {
+    parameters = parameters || {};
 
-  // Override defaults
-  $scope.formData.name = undefined;
-  $scope.motion = UIUtils.motion.default;
-  $scope.entered = false;
+    $scope.formData.useRelative = angular.isDefined(parameters.useRelative) ? parameters.useRelative : $scope.formData.useRelative;
+    $scope.formData.showBalance = angular.isDefined(parameters.showBalance) ? parameters.showBalance : $scope.formData.showBalance;
+    $scope.formData.minData = angular.isDefined(parameters.minData) ? parameters.minData : $scope.formData.minData;
+    $scope.formData.excludedWalletId = parameters.excludedWalletId;
+    $scope.formData.showDefault = (angular.isDefined(parameters.showDefault) ? parameters.showDefault :  $scope.formData.showDefault)
+      && ($scope.formData.excludedWalletId !== 'default');
 
-  $scope.enter = function(e, state) {
-    // First enter
-    if (!$scope.entered) {
-      $scope.entered = true;
-      $scope.setParameters({
-        showDefault: true,
-        showBalance: true,
-        minData: false
-      });
+  };
 
-      return $scope.load()
-        .then(function() {
-          UIUtils.loading.hide();
-          if (!$scope.wallets) return; // user cancel, or error
-          $scope.addListeners();
-          $scope.showFab('fab-add-wallet');
-        });
+  $scope.load = function(options) {
+
+    options = options || {};
+    $scope.loading = (options.silent !== false);
+    $scope.formData.balance = undefined;
+    $scope.formData.updatingWalletId = undefined;
+    $scope.formData.stopped = false;
+
+    // Load currency, and filter translations (need by 'formatAmount' filter)
+    var jobs = [];
+
+    jobs.push(csCurrency.name()
+      .then(function(currency) {
+        $scope.currency = currency;
+        return filterTranslations.ready();
+      }));
+
+    // Get children wallets
+    $scope.defaultWallet = $scope.formData.showDefault ? csWallet : undefined;
+    if (!$scope.wallets) {
+      jobs.push(
+        csWallet.children.all()
+          .then(function(children) {
+            $scope.wallets=children;
+            UIUtils.loading.hide();
+          })
+      );
     }
-    // If already enter
-    else {
-      // Re-add listeners
-      $scope.addListeners();
-      if ($scope.formData.stopped) {
-        $scope.loading = false;
-        $scope.formData.stopped = false;
+
+    // Prepare load options
+    var walletLoadOptions = {
+      silent: true,
+      minData: $scope.formData.minData,
+      sources: $scope.formData.showBalance,
+      tx: {
+        enable: false
+      },
+      api: true
+    };
+    var hasLoadError = false;
+    var loadCounter = 0;
+    var now = Date.now();
+    var balance = 0;
+    return (jobs.length ? $q.all(jobs) : $q.when())
+      // Load wallet data (apply a timeout between each wallet)
+      .then(function() {
+        var wallets = $scope.formData.showDefault ? [csWallet].concat($scope.wallets) : $scope.wallets;
+        if (!wallets.length) return;
+        console.debug("[wallets] Loading {0} wallets...".format(wallets.length));
+        return wallets.reduce(function(res, wallet) {
+            var skip= !options.refresh && wallet.isDataLoaded(walletLoadOptions);
+            if (skip) {
+              console.debug("[wallets] Wallet #{0} already loaded. Skipping".format(wallet.id));
+              return res.then(function(){
+                balance += wallet.data.balance;
+                $scope.updateWalletView(wallet.id);
+              });
+            }
+            loadCounter++;
+            return res.then(function() {
+              if ($scope.formData.stopped) return; // skip if stopped
+              // Loading next wallet, after waiting some time
+                $scope.formData.updatingWalletId = wallet.id;
+                var loadPromise;
+                if (options.refresh && wallet.data.loaded) {
+                  var refreshOptions = angular.merge({
+                    // Refresh requirements if member account
+                    requirements: (!wallet.data.requirements.loaded || wallet.data.requirements.isMember || wallet.data.requirements.wasMember || wallet.data.requirements.pendingMembership)
+                  }, walletLoadOptions);
+                  loadPromise = wallet.refreshData(refreshOptions);
+                }
+                else {
+                  loadPromise = wallet.loadData(walletLoadOptions);
+                }
+
+                loadPromise.then(function(walletData) {
+                  balance += walletData.balance;
+                  $scope.updateWalletView(wallet.id);
+                })
+                .catch(function(err) {
+                  console.error("[wallets] Error while loading data of wallet #{0}".format(wallet.id), err);
+                  hasLoadError = true;
+                });
+                return loadPromise;
+            });
+          }, $q.when());
+      })
+      .then(function() {
+        if (hasLoadError) {
+          return UIUtils.alert.error('ERROR.LOAD_WALLET_LIST_FAILED')
+            .then(function() {
+              $scope.resetData();
+              $scope.cancel();
+            });
+        }
+        // Stop
+        if ($scope.formData.stopped) return;
+        if (loadCounter) {
+          console.debug("[wallets] Loaded data of {0} wallet(s) in {1}ms".format(loadCounter, (Date.now() - now)));
+        }
+        $scope.formData.balance = balance;
         $scope.formData.updatingWalletId = undefined;
+        $scope.loading = false;
+        UIUtils.loading.hide();
         $scope.updateView();
-      }
+      })
+      .catch(function(err) {
+        $scope.resetData();
+        if (err && err === 'CANCELLED') {
+          $scope.cancel();
+          throw err;
+        }
+        return UIUtils.onError('ERROR.LOAD_WALLET_LIST_FAILED')(err);
+      });
+  };
+
+  $scope.filterFn = function(parameters) {
+    return function(wallet) {
+      return !parameters || wallet.id !== parameters.excludedWalletId;
     }
   };
-  $scope.$on('$ionicView.enter', $scope.enter);
 
-  $scope.leave = function() {
-    $scope.formData.stopped = true;
+
+  // Clean controller data
+  $scope.resetData = function() {
+    console.debug("[wallets] Cleaning wallet list");
+    $scope.wallets = null;
+    $scope.loading = true;
+    $scope.entered = false;
+    $scope.formData.balance = undefined;
     $scope.formData.updatingWalletId = undefined;
-    $scope.loading = false;
-    $scope.removeListeners();
   };
-  $scope.$on('$ionicView.leave', $scope.leave);
 
-  $scope.cancel = function() {
-    $scope.showHome();
-  };
+  $scope.updateView = function(walletId) {
+    if (!$scope.wallets || !$scope.wallets.length) return;
 
-  $scope.select = function(event, wallet) {
-    if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return;
-    if (wallet.isDefault()) {
-      $state.go('app.view_wallet');
+    var selectorSuffix = walletId && (' #wallet-' + walletId) || '';
+
+    if ($scope.motion) {
+      $scope.motion.show({selector: '.list .item.item-wallet' + selectorSuffix, ink: true});
     }
     else {
-      $state.go('app.view_wallet_by_id', {id: wallet.id});
+      UIUtils.ink({selector: '.list .item.item-wallet' + selectorSuffix});
     }
-    event.preventDefault();
   };
 
-  $scope.editWallet = function(event, wallet) {
-
-    event.preventDefault();
+  $scope.updateWalletView = function(walletId) {
+    if ($scope.motion) {
+      $scope.motion.show({selector: '.list #wallet-' + walletId, ink: true});
+    }
+    else {
+      UIUtils.ink({selector: '.list #wallet-' + walletId});
+    }
+  };
 
-    return $scope.showEditPopup(wallet)
-      .then(function(newName) {
-        if (!newName) return;
+  $scope.doUpdate = function(silent) {
+    if ($scope.loading || !$scope.wallets || !$scope.wallets.length || $scope.formData.updatingWalletId) return $q.when();
 
-        // Auth (if encryption is need)
-        return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when())
+    $scope.selectPrevented = true;
+    $timeout(function() {
+      $scope.selectPrevented = false;
+    }, 1000);
 
-          // Save changes
-          .then(function() {
-            wallet.data.localName = newName;
-            csWallet.storeData();
-            UIUtils.loading.hide();
-            $scope.updateView();
-          })
-          .catch(function(err) {
-            if (err === 'CANCELLED') {
-              return UIUtils.loading.hide();
-            }
-            UIUtils.onError('ERROR.SAVE_WALLET_LIST_FAILED')(err);
-          });
+    return $scope.load({silent: silent, refresh: true})
+      .then(function() {
+        $scope.loading = false;
+        $scope.selectPrevented = false;
+        if (silent) {
+          $scope.$broadcast('$$rebind::rebind'); // force rebind
+        }
+        $scope.updateView();
       });
   };
 
-  $scope.downloadAsFile = function() {
-    if (!$scope.wallets) return; // user cancel
-    return csWallet.children.downloadFile();
-  };
-
   $scope.addNewWallet = function(wallet) {
 
     if (!wallet) return $q.reject("Missing 'wallet' argument");
@@ -222,43 +323,188 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl
           return;
         }
 
-        // Avoid to add main wallet again
-        if (csWallet.isUserPubkey(walletData.pubkey)) {
-          UIUtils.loading.hide();
-          UIUtils.alert.error('ERROR.COULD_NOT_ADD_MAIN_WALLET');
-          return;
-        }
+        // Avoid to add main wallet again
+        if (csWallet.isUserPubkey(walletData.pubkey)) {
+          UIUtils.loading.hide();
+          UIUtils.alert.error('ERROR.COULD_NOT_ADD_MAIN_WALLET');
+          return;
+        }
+
+        // Avoid to add exists wallet again
+        if (csWallet.children.hasPubkey(walletData.pubkey)) {
+          UIUtils.loading.hide();
+          UIUtils.alert.error('ERROR.COULD_NOT_ADD_EXISTING_WALLET');
+          return;
+        }
+
+        console.debug("[wallet] Adding secondary wallet {"+walletData.pubkey.substring(0,8)+"}");
+
+        // Add the child wallet
+        return $scope.addNewWallet(wallet)
+          .then(function() {
+            UIUtils.loading.hide();
+            $scope.updateView();
+          });
+      })
+      .catch(function(err) {
+        if (err === 'CANCELLED') {
+          // Silent
+          UIUtils.loading.hide();
+        }
+      });
+  };
+
+  /* -- Method to override by subclasses-- */
+
+  $scope.addListenersOnWallet = function(wallet) {
+    // Can be override by subclass
+  };
+
+  $scope.cancel = function() {
+    console.warn("cancel() must be implement by subclass")
+  };
+
+  $scope.select = function(event, wallet) {
+    console.warn("select() must be implement by subclass")
+  };
+}
+
+function WalletSelectModalController($scope, $controller, parameters) {
+  'ngInject';
+
+  // Initialize the super class and extend it.
+  angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope}));
+
+  $scope.$on('modal.shown', function() {
+    $scope.setParameters(parameters);
+    $scope.load();
+  });
+
+  $scope.cancel = function() {
+    $scope.closeModal();
+  };
+
+  $scope.select = function(event, wallet) {
+    if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return;
+    $scope.closeModal(wallet);
+  };
+
+  // Default actions
+  if (parameters) {
+    $scope.setParameters(parameters);
+  }
+}
+
+function WalletListViewController($scope, $controller, $state, $timeout, $q, $translate, $ionicPopover, $ionicPopup,
+                              ModalUtils, UIUtils, Modals, csCurrency, csSettings, csWallet){
+  'ngInject';
+
+  $scope.settings = csSettings.data;
+  $scope.listeners = [];
+
+  // Initialize the super class and extend it.
+  angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope, parameters: {}}));
+
+  // Override defaults
+  $scope.formData.name = undefined;
+  $scope.motion = UIUtils.motion.default;
+  $scope.entered = false;
+
+  $scope.enter = function(e, state) {
+    // First enter
+    if (!$scope.entered) {
+      $scope.entered = true;
+      $scope.setParameters({
+        showDefault: true,
+        showBalance: true,
+        minData: false
+      });
+
+      return $scope.load()
+        .then(function() {
+          UIUtils.loading.hide();
+          if (!$scope.wallets) return; // user cancel, or error
+          $scope.addListeners();
+          $scope.showFab('fab-add-wallet');
+        });
+    }
+    // If already enter
+    else {
+      // Re-add listeners
+      $scope.addListeners();
+      if ($scope.formData.stopped) {
+        $scope.loading = false;
+        $scope.formData.stopped = false;
+        $scope.formData.updatingWalletId = undefined;
+        $scope.updateView();
+      }
+    }
+  };
+  $scope.$on('$ionicView.enter', $scope.enter);
+
+  $scope.leave = function() {
+    $scope.formData.stopped = true;
+    $scope.formData.updatingWalletId = undefined;
+    $scope.loading = false;
+    $scope.removeListeners();
+  };
+  $scope.$on('$ionicView.leave', $scope.leave);
+
+  $scope.cancel = function() {
+    $scope.showHome();
+  };
+
+  $scope.select = function(event, wallet) {
+    if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return;
+    if (wallet.isDefault()) {
+      $state.go('app.view_wallet');
+    }
+    else {
+      $state.go('app.view_wallet_by_id', {id: wallet.id});
+    }
+    event.preventDefault();
+  };
+
+  $scope.editWallet = function(event, wallet) {
+
+    event.preventDefault();
 
-        // Avoid to add exists wallet again
-        if (csWallet.children.hasPubkey(walletData.pubkey)) {
-          UIUtils.loading.hide();
-          UIUtils.alert.error('ERROR.COULD_NOT_ADD_EXISTING_WALLET');
-          return;
-        }
+    return $scope.showEditPopup(wallet)
+      .then(function(newName) {
+        if (!newName) return;
 
-        console.debug("[wallet] Adding secondary wallet {"+walletData.pubkey.substring(0,8)+"}");
+        // Auth (if encryption is need)
+        return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when())
 
-        // Add the child wallet
-        return $scope.addNewWallet(wallet)
+          // Save changes
           .then(function() {
+            wallet.data.localName = newName;
+            csWallet.storeData();
             UIUtils.loading.hide();
             $scope.updateView();
+          })
+          .catch(function(err) {
+            if (err === 'CANCELLED') {
+              return UIUtils.loading.hide();
+            }
+            UIUtils.onError('ERROR.SAVE_WALLET_LIST_FAILED')(err);
           });
-      })
-      .catch(function(err) {
-        if (err === 'CANCELLED') {
-          // Silent
-          UIUtils.loading.hide();
-        }
       });
   };
 
+  $scope.downloadAsFile = function() {
+    if (!$scope.wallets) return; // user cancel
+    return csWallet.children.downloadFile();
+  };
+
+
+
   $scope.selectAndRemoveWallet = function() {
     $scope.hideActionsPopover();
     return Modals.showSelectWallet({
-        wallets: $scope.wallets,
-        showDefault: false
-      })
+      wallets: $scope.wallets,
+      showDefault: false
+    })
       .then(function(wallet) {
         if (!wallet || !wallet.id) return;
 
@@ -287,13 +533,13 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl
       console.debug("[wallet] Adding secondary wallet {"+authData.pubkey.substring(0,8)+"}");
       var wallet = csWallet.children.instance();
       return wallet.login({
-          authData: authData,
-          // Load data options :
-          minData: true,
-          sources: true,
-          api: false,
-          success: UIUtils.loading.show
-        })
+        authData: authData,
+        // Load data options :
+        minData: true,
+        sources: true,
+        api: false,
+        success: UIUtils.loading.show
+      })
         .then(function(walletData) {
           walletData.localName = authData.localName;
           return $scope.addNewWallet(wallet);
@@ -301,8 +547,8 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl
     };
 
     return ModalUtils.show(
-        'templates/wallet/list/modal_import_file.html',
-        'WalletListImportModalCtrl'
+      'templates/wallet/list/modal_import_file.html',
+      'WalletListImportModalCtrl'
     )
       .then(function(items){
         if (!items || !items.length) return; // User cancel
@@ -451,13 +697,13 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl
   var inheritedUpdateView = $scope.updateView;
   $scope.updateView = function() {
     inheritedUpdateView();
-    $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind
+    $scope.$broadcast('$$rebind::rebind'); // force rebind
   };
 
   var inheritedUpdateWalletView = $scope.updateWalletView;
   $scope.updateWalletView = function(walletId) {
     inheritedUpdateWalletView(walletId);
-    $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind
+    $scope.$broadcast('$$rebind::rebind'); // force rebind
   };
 
   // Detect changes in settings useRelative
@@ -468,233 +714,19 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl
   }, true);
 }
 
-function WalletSelectModalController($scope, $q, $timeout, UIUtils, filterTranslations, csSettings, csCurrency, csWallet, parameters){
-  'ngInject';
-
-  $scope.loading = true;
-  $scope.wallets = null;
-  $scope.formData = {
-    useRelative: csSettings.data.useRelative,
-    showDefault: true,
-    showBalance: false,
-    balance: undefined,
-    updatingWalletId: undefined,
-    stopped: false,
-    minData: true
-  };
-  $scope.motion = null; // no animation
-
-  $scope.setParameters = function(parameters) {
-    parameters = parameters || {};
-
-    $scope.formData.useRelative = angular.isDefined(parameters.useRelative) ? parameters.useRelative : $scope.formData.useRelative;
-
-    $scope.formData.showDefault = angular.isDefined(parameters.showDefault) ? parameters.showDefault : $scope.formData.showDefault;
-
-    $scope.formData.showBalance = angular.isDefined(parameters.showBalance) ? parameters.showBalance : $scope.formData.showBalance;
-
-    $scope.formData.minData = angular.isDefined(parameters.minData) ? parameters.minData : $scope.formData.minData;
-  };
-
-  $scope.load = function(options) {
-
-    options = options || {};
-    $scope.loading = angular.isUndefined(options.silent) || !options.silent;
-    $scope.formData.balance = undefined;
-    $scope.formData.updatingWalletId = undefined;
-    $scope.formData.stopped = false;
-
-    // Load currency, and filter translations (need by 'formatAmount' filter)
-    var jobs = [];
-
-    jobs.push(csCurrency.name()
-      .then(function(currency) {
-        $scope.currency = currency;
-        return filterTranslations.ready();
-      }));
-
-    // Get children wallets
-    $scope.defaultWallet = $scope.formData.showDefault ? csWallet : undefined;
-    if (!$scope.wallets) {
-      jobs.push(
-        csWallet.children.all()
-          .then(function(children) {
-            $scope.wallets=children;
-            UIUtils.loading.hide();
-          })
-      );
-    }
-
-    // Prepare load options
-    var walletLoadOptions = {
-      silent: true,
-      minData: $scope.formData.minData,
-      sources: $scope.formData.showBalance,
-      tx: {
-        enable: false
-      },
-      api: true
-    };
-    var hasLoadError = false;
-    var loadCounter = 0;
-    var now = Date.now();
-    var balance = 0;
-    return (jobs.length ? $q.all(jobs) : $q.when())
-      // Load wallet data (apply a timeout between each wallet)
-      .then(function() {
-        var wallets = $scope.formData.showDefault ? [csWallet].concat($scope.wallets) : $scope.wallets;
-        if (!wallets.length) return;
-        console.debug("[wallets] Loading {0} wallets...".format(wallets.length));
-        return wallets.reduce(function(res, wallet) {
-            var skip= !options.refresh && wallet.isDataLoaded(walletLoadOptions);
-            if (skip) {
-              console.debug("[wallets] Wallet #{0} already loaded. Skipping".format(wallet.id));
-              return res.then(function(){
-                balance += wallet.data.balance;
-                $scope.updateWalletView(wallet.id);
-              });
-            }
-            loadCounter++;
-            return res.then(function() {
-              if ($scope.formData.stopped) return; // skip if stopped
-              // Loading next wallet, after waiting some time
-                $scope.formData.updatingWalletId = wallet.id;
-                var loadPromise;
-                if (options.refresh && wallet.data.loaded) {
-                  var refreshOptions = angular.merge({
-                    // Refresh requirements if member account
-                    requirements: (!wallet.data.requirements.loaded || wallet.data.requirements.isMember || wallet.data.requirements.wasMember || wallet.data.requirements.pendingMembership)
-                  }, walletLoadOptions);
-                  loadPromise = wallet.refreshData(refreshOptions);
-                }
-                else {
-                  loadPromise = wallet.loadData(walletLoadOptions);
-                }
-
-                loadPromise.then(function(walletData) {
-                  balance += walletData.balance;
-                  $scope.updateWalletView(wallet.id);
-                })
-                .catch(function(err) {
-                  console.error("[wallets] Error while loading data of wallet #{0}".format(wallet.id), err);
-                  hasLoadError = true;
-                });
-                return loadPromise;
-            });
-          }, $q.when());
-      })
-      .then(function() {
-        if (hasLoadError) {
-          return UIUtils.alert.error('ERROR.LOAD_WALLET_LIST_FAILED')
-            .then(function() {
-              $scope.resetData();
-              $scope.cancel();
-            });
-        }
-        // Stop
-        if ($scope.formData.stopped) return;
-        if (loadCounter) {
-          console.debug("[wallets] Loaded data of {0} wallet(s) in {1}ms".format(loadCounter, (Date.now() - now)));
-        }
-        $scope.formData.balance = balance;
-        $scope.formData.updatingWalletId = undefined;
-        $scope.loading = false;
-        UIUtils.loading.hide();
-        $scope.updateView();
-      })
-      .catch(function(err) {
-        $scope.resetData();
-        if (err && err === 'CANCELLED') {
-          $scope.cancel();
-          throw err;
-        }
-        return UIUtils.onError('ERROR.LOAD_WALLET_LIST_FAILED')(err);
-      });
-  };
-
-  $scope.$on('modal.shown', function() {
-    $scope.load();
-  });
-
-  $scope.cancel = function() {
-    $scope.closeModal();
-  };
-
-  $scope.select = function(event, wallet) {
-    if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return;
-    $scope.closeModal(wallet);
-  };
-
-  // Clean controller data
-  $scope.resetData = function() {
-    console.debug("[wallets] Cleaning wallet list");
-    $scope.wallets = null;
-    $scope.loading = true;
-    $scope.entered = false;
-    $scope.formData.balance = undefined;
-    $scope.formData.updatingWalletId = undefined;
-  };
-
-  $scope.updateView = function(walletId) {
-    if (!$scope.wallets || !$scope.wallets.length) return;
-
-    var selectorSuffix = walletId && (' #wallet-' + walletId) || '';
-
-    if ($scope.motion) {
-      $scope.motion.show({selector: '.list .item.item-wallet' + selectorSuffix, ink: true});
-    }
-    else {
-      UIUtils.ink({selector: '.list .item.item-wallet' + selectorSuffix});
-    }
-  };
-
-  $scope.updateWalletView = function(walletId) {
-    if ($scope.motion) {
-      $scope.motion.show({selector: '.list #wallet-' + walletId, ink: true});
-    }
-    else {
-      UIUtils.ink({selector: '.list #wallet-' + walletId});
-    }
-  };
-
-  $scope.doUpdate = function(silent, event) {
-    if ($scope.loading || !$scope.wallets || !$scope.wallets.length || $scope.formData.updatingWalletId) return $q.when();
-
-    $scope.selectPrevented = true;
-    $timeout(function() {
-      $scope.selectPrevented = false;
-    }, 1000);
-
-    return $scope.load({silent: silent, refresh: true})
-      .then(function() {
-        $scope.loading = false;
-        $scope.selectPrevented = false;
-        if (silent) {
-          $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind
-        }
-        $scope.updateView();
-      });
-  };
-
-  // Default actions
-  $scope.setParameters(parameters);
-
-}
 
-function PopoverWalletSelectModalController($scope, $controller, UIUtils) {
+function WalletSelectPopoverController($scope, $controller, UIUtils, parameters) {
   'ngInject';
 
   // Initialize the super class and extend it.
-  angular.extend(this, $controller('WalletSelectModalCtrl', {$scope: $scope, parameters: {
-    showDefault: true,
-    showBalance: false
-  }}));
+  angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope}));
 
   // Disable list motion
   $scope.motion = null;
 
   $scope.$on('popover.shown', function() {
     if ($scope.loading) {
+      $scope.setParameters(parameters);
       $scope.load();
     }
   });
@@ -703,12 +735,14 @@ function PopoverWalletSelectModalController($scope, $controller, UIUtils) {
     if (!$scope.wallets || !$scope.wallets.length) return;
 
     UIUtils.ink({selector: '.popover-wallets .list .item'});
+    $scope.$broadcast('$$rebind::rebind'); // force rebind
   };
 
   $scope.select = function(event, wallet) {
     if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; // no selection
     $scope.closePopover(wallet);
   };
+
 }
 
 function WalletListImportModalController($scope, $timeout, BMA, csWallet) {
diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js
index db0194e04..6344a296d 100644
--- a/www/js/controllers/wot-controllers.js
+++ b/www/js/controllers/wot-controllers.js
@@ -1209,8 +1209,8 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo
 
   // Update view
   $scope.updateView = function() {
-    $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
-    $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind
+    $scope.$broadcast('$$rebind::balance'); // force rebind balance
+    $scope.$broadcast('$$rebind::rebind'); // force rebind
     $scope.motion.show();
   };
 
diff --git a/www/js/services/crypto-services.js b/www/js/services/crypto-services.js
index 75ebb37b1..8201a3134 100644
--- a/www/js/services/crypto-services.js
+++ b/www/js/services/crypto-services.js
@@ -217,40 +217,47 @@ angular.module('cesium.crypto.services', ['cesium.utils.services'])
        */
       this.box_keypair_from_sign = function (signKeyPair) {
         if (signKeyPair.boxSk && signKeyPair.boxPk) return $q.when(signKeyPair);
-        return $q.when(that.nacl.crypto_box_keypair_from_sign_sk(signKeyPair.signSk));
+        return $q(function (resolve, reject) {
+          try {
+            // TODO: waiting for a new version of js-nacl, with missing functions expose
+            //resolve(that.nacl.crypto_box_keypair_from_sign_sk(signPk);
+
+            resolve(crypto_box_keypair_from_sign_sk(signPk));
+          }
+          catch(err) {
+            reject(err);
+          }
+        });
       };
 
       /**
        * Compute the box public key, from a sign public key
        */
       this.box_pk_from_sign = function (signPk) {
-        return $q(function (resolve, reject) {
+        return $q(function(resolve, reject) {
           try {
-            var pka = check_injectBytes("box_pk_from_sign", "signPk", signPk, that.nacl.nacl_raw._crypto_sign_publickeybytes());
-            var pk = new Target(that.nacl.nacl_raw._crypto_box_publickeybytes());
-            check("_crypto_sign_ed25519_pk_to_curve25519", that.nacl.nacl_raw._crypto_sign_ed25519_pk_to_curve25519(pk.address, pka));
-            FREE(pka);
-            resolve(pk.extractBytes());
+            // TODO: waiting for a new version of js-nacl, with missing functions expose
+            //resolve(that.nacl.crypto_box_pk_from_sign_pk(signPk));
+
+            resolve(crypto_box_pk_from_sign_pk(signPk));
           }
-          catch (err) {
+          catch(err) {
             reject(err);
           }
         });
       };
 
       this.box_sk_from_sign = function (signSk) {
-        return $q(function (resolve, reject) {
+        return $q(function(resolve, reject) {
           try {
-            var ska = check_injectBytes("box_sk_from_sign", "signSk", signSk, that.nacl.nacl_raw._crypto_sign_secretkeybytes());
-            var sk = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes());
-            that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(sk.address, ska);
-            FREE(ska);
-            resolve(sk.extractBytes());
+            // TODO: waiting for a new version of js-nacl, with missing functions expose
+            //resolve(that.nacl.crypto_box_sk_from_sign_sk(signSk));
+            resolve(crypto_box_sk_from_sign_sk(signSk));
           }
-          catch (err) {
+          catch(err) {
             reject(err);
           }
-        });
+        })
       };
 
       /**
@@ -294,7 +301,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services'])
           }
 
           try {
-            var message = crypto_box_open(ciphertextBin, nonce, senderPk, recipientSk);
+            var message = that.nacl.crypto_box_open(ciphertextBin, nonce, senderPk, recipientSk);
             resolve(that.nacl.decode_utf8(message));
           }
           catch (err) {
@@ -447,6 +454,40 @@ angular.module('cesium.crypto.services', ['cesium.utils.services'])
         open: that.box_open
       };
 
+      /*--
+        start WORKAROUND - Publish missing functions (see PR js-nacl: https://github.com/tonyg/js-nacl/pull/54)
+      -- */
+
+      function crypto_box_keypair_from_sign_sk(sk) {
+        var ska = check_injectBytes("crypto_box_keypair_from_sign_sk", "sk", sk,
+          that.nacl.nacl_raw._crypto_sign_secretkeybytes());
+        var skb = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes());
+        check("_crypto_sign_ed25519_sk_to_curve25519",
+          that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska));
+        FREE(ska);
+        return that.nacl.crypto_box_keypair_from_raw_sk(skb.extractBytes());
+      }
+
+      function crypto_box_pk_from_sign_pk(pk) {
+        var pka = check_injectBytes("crypto_box_pk_from_sign_pk", "pk", pk,
+          that.nacl.nacl_raw._crypto_sign_publickeybytes());
+        var pkb = new Target(that.nacl.nacl_raw._crypto_box_publickeybytes());
+        check("_crypto_sign_ed25519_pk_to_curve25519",
+          that.nacl.nacl_raw._crypto_sign_ed25519_pk_to_curve25519(pkb.address, pka));
+        FREE(pka);
+        return pkb.extractBytes();
+      }
+
+      function crypto_box_sk_from_sign_sk(sk) {
+        var ska = check_injectBytes("crypto_box_sk_from_sign_sk", "sk", sk,
+          that.nacl.nacl_raw._crypto_sign_secretkeybytes());
+        var skb = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes());
+        check("_crypto_sign_ed25519_sk_to_curve25519",
+          that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska));
+        FREE(ska);
+        return skb.extractBytes();
+      }
+
       function check_length(function_name, what, thing, expected_length) {
         if (thing.length !== expected_length) {
           throw {message: "nacl." + function_name + " expected " +
@@ -454,20 +495,6 @@ angular.module('cesium.crypto.services', ['cesium.utils.services'])
         }
       }
 
-      function crypto_box_open(ciphertext, nonce, pk, sk) {
-        var c = injectBytes(ciphertext, that.nacl.nacl_raw._crypto_box_boxzerobytes());
-        var na = check_injectBytes("crypto_box_open",
-          "nonce", nonce, that.nacl.nacl_raw._crypto_box_noncebytes());
-        var pka = check_injectBytes("crypto_box_open",
-          "pk", pk, that.nacl.nacl_raw._crypto_box_publickeybytes());
-        var ska = check_injectBytes("crypto_box_open",
-          "sk", sk, that.nacl.nacl_raw._crypto_box_secretkeybytes());
-        var m = new Target(ciphertext.length + that.nacl.nacl_raw._crypto_box_boxzerobytes());
-        check("_crypto_box_open", that.nacl.nacl_raw._crypto_box_open(m.address, c, m.length, 0, na, pka, ska));
-        free_all([c, na, pka, ska]);
-        return m.extractBytes(that.nacl.nacl_raw._crypto_box_zerobytes());
-      }
-
       function check(function_name, result) {
         if (result !== 0) {
           throw {message: "nacl_raw." + function_name + " signalled an error"};
@@ -524,6 +551,11 @@ angular.module('cesium.crypto.services', ['cesium.utils.services'])
         this.address = null;
         return result;
       };
+
+      /*--
+        end of WORKAROUND
+      -- */
+
     }
     FullJSServiceFactory.prototype = new CryptoAbstractService();
 
diff --git a/www/js/services/modal-services.js b/www/js/services/modal-services.js
index e1d792480..fd024fff9 100644
--- a/www/js/services/modal-services.js
+++ b/www/js/services/modal-services.js
@@ -111,11 +111,11 @@ angular.module('cesium.modal.services', ['cesium.utils.services'])
     options = options ? options : {} ;
     options.animation = options.animation || 'slide-in-up';
 
-    // var focusFirstInput = false;
-    // // removeIf(device)
-    // focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false;
-    // // endRemoveIf(device)
-    // options.focusFirstInput = focusFirstInput;
+    var focusFirstInput = false;
+    // removeIf(device)
+    focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false;
+    // endRemoveIf(device)
+    options.focusFirstInput = focusFirstInput;
 
     // If modal has a controller
     if (controller) {
@@ -298,18 +298,41 @@ angular.module('cesium.modal.services', ['cesium.utils.services'])
 
 })
 
-.factory('csPopovers', function($rootScope, $translate, $ionicPopup, $timeout, UIUtils) {
+.factory('csPopovers', function($rootScope, $translate, $ionicPopup, $timeout, UIUtils, $controller) {
     'ngInject';
 
     function showSelectWallet(event, options) {
-      options = options || {};
+      options = options || {};
+
+      var parameters = options.parameters || {};
+      delete options.parameters;
+
       var scope = options.scope && options.scope.$new() || $rootScope.$new(true);
-      scope.parameters = options;
-      delete options.scope;
-      return UIUtils.popover.show(event, angular.merge({
-        templateUrl :'templates/wallet/list/popover_wallets.html',
-        autoremove: true
-      }, options));
+      options.scope = scope;
+      options.templateUrl = 'templates/wallet/list/popover_wallets.html';
+      options.autoremove = true;
+
+      // Initialize the popover controller, with parameters
+      angular.extend(this, $controller('WalletSelectPopoverCtrl', {$scope: options.scope, parameters: parameters}));
+
+      var afterShowSaved = options.afterShow;
+      options.afterShow = function(popover) {
+
+        // Add a missing method, to close the popover
+        scope.closePopover = function(res) {
+          popover.scope.closePopover(res);
+        };
+
+        // Execute default afterShow fn, if any
+        if (afterShowSaved) afterShowSaved(popover);
+      };
+      // Show the popover
+      return UIUtils.popover.show(event, options)
+        .then(function(res) {
+          // Then destroy the scope
+          scope.$destroy();
+          return res;
+        });
     }
 
     return {
diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js
index 9c9b84107..3c18ed4f9 100644
--- a/www/js/services/utils-services.js
+++ b/www/js/services/utils-services.js
@@ -412,10 +412,9 @@ angular.module('cesium.utils.services', [])
 
     options = options || {};
     options.templateUrl = options.templateUrl ? options.templateUrl : 'templates/common/popover_copy.html';
-    options.scope = options.scope && options.scope || $rootScope;
+    options.scope = options.scope || $rootScope;
     options.scope.popovers = options.scope.popovers || {};
     options.autoselect = options.autoselect || false;
-    options.bindings = options.bindings || {};
     options.autoremove = angular.isDefined(options.autoremove) ? options.autoremove : true;
     options.backdropClickToClose = angular.isDefined(options.backdropClickToClose) ? options.backdropClickToClose : true;
     options.focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false;
@@ -426,7 +425,9 @@ angular.module('cesium.utils.services', [])
       popover.deferred=deferred;
       popover.options=options;
       // Fill the popover scope
-      angular.merge(popover.scope, options.bindings);
+      if (options.bindings) {
+        angular.merge(popover.scope, options.bindings);
+      }
       $timeout(function() { // This is need for Firefox
         popover.show(event)
           .then(function() {
diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js
index 97b4a431b..b787c38b8 100644
--- a/www/js/services/wallet-services.js
+++ b/www/js/services/wallet-services.js
@@ -1997,7 +1997,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se
     },
 
     getChildWalletById = function(id) {
-      return _.find(data.children|| [], function(child) {return child.id == id;});
+      return (id !== 'default') && _.find(data.children|| [], function(child) {return child.id == id;}) || undefined;
     },
 
     getChildWalletByPubkey = function(pubkey) {
diff --git a/www/plugins/es/js/controllers/app-controllers.js b/www/plugins/es/js/controllers/app-controllers.js
index f595e7930..c324806e7 100644
--- a/www/plugins/es/js/controllers/app-controllers.js
+++ b/www/plugins/es/js/controllers/app-controllers.js
@@ -67,7 +67,7 @@ function ESMenuExtendController($scope, $state, $controller, UIUtils, csWallet)
   angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope}));
 
   $scope.showRegistryLookupView = function() {
-    $state.go(UIUtils.screen.isSmall() ? 'app.registry_lookup': 'app.registry_lookup_lg');
+    $state.go(UIUtils.screen.isSmall() ? 'app.wot_lookup.tab_registry': 'app.registry_lookup_lg');
   };
 
   $scope.showNotificationsPopover = function(event) {
diff --git a/www/plugins/es/js/controllers/document-controllers.js b/www/plugins/es/js/controllers/document-controllers.js
index f6e11c46f..3e9f52126 100644
--- a/www/plugins/es/js/controllers/document-controllers.js
+++ b/www/plugins/es/js/controllers/document-controllers.js
@@ -147,7 +147,7 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout,
       });
   };
 
-  $scope.remove = function(index) {
+  $scope.remove = function(index, options) {
     var doc = $scope.search.results[index];
     if (!doc) return;
 
diff --git a/www/plugins/es/js/controllers/message-controllers.js b/www/plugins/es/js/controllers/message-controllers.js
index b4b49d291..283e5252b 100644
--- a/www/plugins/es/js/controllers/message-controllers.js
+++ b/www/plugins/es/js/controllers/message-controllers.js
@@ -62,7 +62,7 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services'])
         url: "/wallets/:id/message",
         views: {
           'menuContent': {
-            templateUrl: "plugins/es/templates/message/lookup.html"
+            templateUrl: "plugins/es/templates/message/lookup_by_id.html"
           }
         }
       })
@@ -104,7 +104,7 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services'])
       })
 
       .state('app.user_messages_lg_outbox', {
-        url: "/wallets/:id/message/lg/outbox",
+        url: "/user/message/lg/outbox",
         views: {
           'menuContent': {
             templateUrl: "plugins/es/templates/message/lookup_lg.html",
@@ -118,7 +118,7 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services'])
       })
 
       .state('app.user_messages_lg_outbox_by_id', {
-        url: "/user/message/lg/outbox",
+        url: "/wallets/:id/message/lg/outbox",
         views: {
           'menuContent': {
             templateUrl: "plugins/es/templates/message/lookup_lg.html",
@@ -189,6 +189,7 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto
 
   var defaultSearchLimit = 40;
   var wallet;
+  var selectPrevented = false;
 
   $scope.search = {
     loading: true,
@@ -205,43 +206,45 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto
   $scope.fabButtonNewMessageId = undefined;
 
   $scope.enter = function(s, state) {
-    wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet;
-    if (!wallet) {
-      UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID');
-      return $scope.showHome();
-    }
+    // First enter
+    if ($scope.search.loading) {
+      wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet;
+      if (!wallet) {
+        UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID');
+        return $scope.showHome();
+      }
 
-    $scope.isDefaultWallet = wallet.isDefault();
-    $scope.walletId = wallet.id;
+      $scope.isDefaultWallet = wallet.isDefault();
+      $scope.walletId = wallet.id;
 
-    wallet.auth({minData: true})
-      .then(function() {
-        if (!$scope.entered) {
-          $scope.entered = true;
-          $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox';
-          $scope.load();
-        }
+      wallet.auth({minData: true})
+        .then(function() {
+          if (!$scope.entered) {
+            $scope.entered = true;
+            $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox';
+            $scope.load();
+          }
 
-        if ($scope.fabButtonNewMessageId) {
-          $scope.showFab($scope.fabButtonNewMessageId);
-        }
-      })
-      .catch(function(err) {
-        if ('CANCELLED' === err) {
-          $ionicHistory.nextViewOptions({
-            historyRoot: true
-          });
-          $state.go('app.home');
-        }
-    });
+          if ($scope.fabButtonNewMessageId) {
+            $scope.showFab($scope.fabButtonNewMessageId);
+          }
+        })
+        .catch(function(err) {
+          if ('CANCELLED' === err) {
+            $ionicHistory.nextViewOptions({
+              historyRoot: true
+            });
+            $scope.showHome();
+          }
+      });
+    }
+    // Not first entering: refresh the view
+    else {
+      $scope.updateView();
+    }
   };
   $scope.$on('$ionicView.enter', $scope.enter);
 
-
-  $scope.refresh = function(silent) {
-    return $scope.load(undefined, undefined, silent);
-  };
-
   $scope.load = function(from, size, silent) {
 
     var options = angular.copy($scope.search.options);
@@ -279,15 +282,11 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto
       });
   };
 
-  $scope.setType = function(type) {
-    $scope.type = type;
-    $scope.load();
-  };
-
   $scope.updateView = function() {
     if ($scope.motion && $scope.motion.ionListClass && $scope.search.results.length) {
       $scope.motion.show({selector: '.view-messages .list .item'});
     }
+    $scope.$broadcast('$$rebind::rebind'); // notifier binder
   };
 
   $scope.showMore = function() {
@@ -332,9 +331,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto
     UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE')
       .then(function(confirm) {
         if (confirm) {
-          esMessage.remove(message.id, $scope.type)
+          esMessage.remove(message.id, $scope.type, {walletId: $scope.walletId})
             .then(function () {
               $scope.search.results.splice(index,1); // remove from messages array
+              $scope.updateView();
               UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED');
             })
             .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED'));
@@ -349,9 +349,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto
     UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE_ALL')
       .then(function(confirm) {
         if (confirm) {
-          esMessage.removeAll($scope.type)
+          esMessage.removeAll($scope.type, {walletId: $scope.walletId})
             .then(function () {
               $scope.search.results.splice(0,$scope.search.results.length); // reset array
+              $scope.updateView();
               UIUtils.toast.show('MESSAGE.INFO.All_MESSAGE_REMOVED');
             })
             .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_All_MESSAGES_FAILED'));
@@ -379,13 +380,33 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto
     return $scope.load();
   };
 
-  $scope.select = function(message) {
-    if (!wallet || wallet.isDefault()) {
-      $state.go('app.user_view_message', {type: $scope.type, messageId:message.id});
-    }
-    else {
-      $state.go('app.user_view_message_by_id', {type: $scope.type, messageId:message.id, id: $scope.walletId});
-    }
+
+  $scope.refresh = function(silent) {
+    selectPrevented = true; // Will disable select() to open the message
+    return $scope.load(undefined, undefined, silent)
+      .then(function() {
+        selectPrevented = false;
+      })
+      .catch(function() {
+        selectPrevented = false;
+      });
+  };
+
+  $scope.select = function(message, event) {
+    if (event.isDefaultPrevented() || $scope.search.loading || selectPrevented) return; // skip
+
+    // Add a timeout, to be sure the refres action was not called before
+    return $timeout(function() {
+      if (selectPrevented || event.isDefaultPrevented()) return; // skip
+      event.preventDefault();
+
+      if ($scope.walletId === 'default') {
+        return $state.go('app.user_view_message', {type: $scope.type, messageId:message.id});
+      }
+      else {
+        return $state.go('app.user_view_message_by_id', {type: $scope.type, messageId:message.id, id: $scope.walletId});
+      }
+    }, 200);
   };
 
   /* -- Modals -- */
@@ -458,22 +479,23 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto
     if (index) {
       $scope.search.results.splice(index,1); // remove from messages array
     }
+    $scope.updateView();
   };
   esMessage.api.data.on.delete($scope, $scope.onMessageDelete);
 
   // Watch user sent message
   $scope.onNewOutboxMessage = function(id) {
-    if ($scope.type != 'outbox') return;
+    if ($scope.type !== 'outbox') return;
     // Add message sent to list
-    $scope.loading = true;
+    $scope.search.loading = true;
     return $timeout(function() {
        // Load the message sent
-        return esMessage.get(id, {type: $scope.type, summary: true});
+        return esMessage.get(id, $scope.type, {summary: true, wallet: wallet});
       }, 500 /*waiting ES propagation*/)
       .then(function(msg) {
         $scope.search.results.splice(0,0,msg);
-        $scope.loading = false;
-        $scope.motion.show({selector: '.view-messages .list .item'});
+        $scope.search.loading = false;
+        $scope.updateView();
       })
       .catch(function() {
         $scope.loading = false;
@@ -483,15 +505,15 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto
 
   // Watch received message
   $scope.onNewInboxMessage = function(notification) {
-    if ($scope.type != 'inbox' || !$scope.entered) return;
+    if ($scope.type !== 'inbox' || !$scope.entered || !wallet.isUserPubkey(notification.issuer)) return;
     // Add message sent to list
-    $scope.loading = true;
+    $scope.search.loading = true;
     // Load the the message
-    return esMessage.get(notification.id, {type: $scope.type, summary: true})
+    return esMessage.get(notification.id, $scope.type, {summary: true, wallet: wallet})
       .then(function(msg) {
         $scope.search.results.splice(0,0,msg);
         $scope.search.loading = false;
-        $scope.motion.show({selector: '.view-messages .list .item'});
+        $scope.updateView();
       })
       .catch(function() {
         $scope.search.loading = false;
@@ -764,65 +786,67 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis
   });
 
   $scope.enter = function(e, state) {
-    if (!$scope.loading) return; // prevent reload if same id
+    // First enter
+    if ($scope.loading) {
 
-    wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet;
-    if (!wallet) {
-      UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID');
-      return $scope.showHome();
-    }
+      wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet;
+      if (!wallet) {
+        UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID');
+        return $scope.showHome();
+      }
 
-    $scope.isDefaultWallet = wallet.isDefault();
-    $scope.walletId = wallet.id;
+      $scope.isDefaultWallet = wallet.isDefault();
+      $scope.walletId = wallet.id;
 
-    var messageId = state.stateParams && state.stateParams.messageId;
-    $scope.type = state.stateParams.type || 'inbox';
+      var messageId = state.stateParams && state.stateParams.messageId;
+      $scope.type = state.stateParams.type || 'inbox';
 
-    // No message id: redirect
-    if (angular.isUndefined(messageId)) {
-      $state.go('app.user_message');
-      return;
-    }
+      // No message id: redirect
+      if (angular.isUndefined(messageId)) {
+        $scope.goBack();
+        return;
+      }
 
-    wallet.auth({minData: true})
-      .then(function () {
-        return $scope.load(messageId, $scope.type);
-      })
-      .then(function(message) {
+      wallet.auth({minData: true})
+        .then(function () {
+          return $scope.load(messageId, $scope.type);
+        })
+        .then(function(message) {
 
-        UIUtils.loading.hide();
-        if (!message) return; // SKip
-
-        $scope.updateView(message);
-        $scope.showFab('fab-view-message-reply');
-
-        // Mark as read
-        if (!message.read) {
-          $timeout(function() {
-            // Message has NOT changed
-            if ($scope.id === message.id) {
-              esMessage.markAsRead(message, {type: $scope.type, wallet: wallet})
-                .then(function() {
-                  console.debug("[message] marked as read");
-                })
-                .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED'));
-            }
-          }, 2000); // 2s
-        }
-      });
+          UIUtils.loading.hide();
+          if (!message) return; // SKip
+
+          $scope.updateView(message);
+          $scope.showFab('fab-view-message-reply');
+
+          // Mark as read
+          if (!message.read) {
+            $timeout(function() {
+              // Message has NOT changed
+              if ($scope.id === message.id) {
+                esMessage.markAsRead(message, {type: $scope.type, wallet: wallet})
+                  .then(function() {
+                    console.debug("[message] marked as read");
+                  })
+                  .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED'));
+              }
+            }, 2000); // 2s
+          }
+        });
+    }
   };
   $scope.$on('$ionicView.enter', $scope.enter);
 
   $scope.load = function(id, type) {
     type = type || 'inbox';
-    return esMessage.get(id, {type: type, wallet: wallet})
+    return esMessage.get(id, type, {wallet: wallet})
       .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED'))
       .then(function(message) {
         if (!message.valid) {
           return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE',
             'MESSAGE.ERROR.MESSAGE_NOT_READABLE')
             .then(function () {
-              $state.go('app.user_message', {type: type});
+              $scope.goBack(true/*clear cache*/);
             });
         }
         return message;
@@ -845,14 +869,9 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis
     UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE')
       .then(function(confirm) {
         if (confirm) {
-          return esMessage.remove($scope.id, $scope.type)
+          return esMessage.remove($scope.id, $scope.type, {wallet: wallet})
             .then(function () {
-              $ionicHistory.nextViewOptions({
-                historyRoot: true
-              });
-              $state.go($scope.type == 'inbox' ? 'app.user_message.tab_inbox' : 'app.user_message.tab_outbox',
-                {type: $scope.type}
-              );
+              $scope.goBack(true/*clear page cache*/);
               UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED');
             })
             .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED'));
@@ -860,6 +879,23 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis
       });
   };
 
+  $scope.goBack = function(clearPageCache) {
+    if (clearPageCache) {
+      $ionicHistory.clearCache($ionicHistory.currentView().stateId); // clear current view
+    }
+    $ionicHistory.nextViewOptions({historyRoot: true});
+    if ($scope.isDefaultWallet) {
+      if ($scope.type) {
+        $state.go('app.user_message.tab_' + $scope.type, {type: $scope.type});
+      }
+    }
+    else {
+      if ($scope.type) {
+        $state.go('app.user_messages_by_id.tab_' + $scope.type, {type: $scope.type, id: $scope.walletId});
+      }
+    }
+  };
+
   /* -- Popover -- */
 
   $scope.showActionsPopover = function(event) {
@@ -895,7 +931,7 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis
             title: prefix + $scope.formData.title,
             content: content,
             isReply: true,
-            wallet: $scope.walletId
+            walletId: wallet.id
           });
       })
       .then(function(sent) {
@@ -914,6 +950,7 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM
   'ngInject';
 
   var defaultSearchLimit = 40;
+  var wallet;
 
   $scope.search = {
     loading : true,
@@ -925,6 +962,15 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM
 
   $scope.$on('popover.shown', function() {
     if ($scope.search.loading) {
+      // TODO manage secondary wallets
+      wallet = $scope.walletId && csWallet.children.get($scope.walletId) || csWallet;
+
+      /* -- wallet listeners -- */
+      if (wallet.isDefault()) {
+        wallet.api.data.on.logout($scope, $scope.resetData);
+        esMessage.api.data.on.new($scope, $scope.onNewMessageNotification);
+      }
+
       $scope.load();
     }
   });
@@ -980,13 +1026,22 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM
   // Listen notifications changes
   $scope.onNewMessageNotification = function(notification) {
     if ($scope.search.loading || $scope.search.loadingMore) return;
+
+    if (!wallet.isUserPubkey(notification.issuer)) return; // skip
+
+    // Prepend to list
     $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', {messageId: notification.id});
+    if ($scope.walletId === 'default') {
+      $state.go('app.user_view_message', {messageId: notification.id});
+    }
+    else {
+      $state.go('app.user_view_message_by_id', {messageId: notification.id, id: $scope.walletId});
+    }
     $scope.closePopover(notification);
   };
 
@@ -1008,7 +1063,7 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM
 
     $timeout(function() {
       parameters = parameters || {};
-      parameters.wallet = $scope.walletId;
+      parameters.walletId = wallet.id;
 
       esModals.showMessageCompose(parameters)
         .then(function(id) {
@@ -1019,9 +1074,7 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM
 
   /* -- listeners -- */
 
-  csWallet.api.data.on.logout($scope, $scope.resetData);
   esHttp.api.node.on.stop($scope, $scope.resetData);
   esHttp.api.node.on.start($scope, $scope.load);
-  esMessage.api.data.on.new($scope, $scope.onNewMessageNotification);
 
 }
diff --git a/www/plugins/es/js/controllers/profile-controllers.js b/www/plugins/es/js/controllers/profile-controllers.js
index abf8be04b..82a612301 100644
--- a/www/plugins/es/js/controllers/profile-controllers.js
+++ b/www/plugins/es/js/controllers/profile-controllers.js
@@ -72,6 +72,8 @@ function ESViewEditProfileController($scope, $q, $timeout, $state, $focus, $tran
       return $scope.showHome();
     }
 
+    $scope.walletId = wallet.id;
+
     return wallet.auth({
         minData: true
       })
@@ -395,9 +397,7 @@ function ESViewEditProfileController($scope, $q, $timeout, $state, $focus, $tran
                 // removeIf(no-device)
                 UIUtils.loading.show();
                 // endRemoveIf(no-device)
-                return esProfile.remove(walletData.pubkey, {
-                    wallet: wallet
-                  })
+                return esProfile.remove(walletData.pubkey, {wallet: wallet})
                   .then(function () {
                     if (wallet.isDefault()) {
                       walletData.name=null; // keep local name, on children wallets
diff --git a/www/plugins/es/js/controllers/registry-controllers.js b/www/plugins/es/js/controllers/registry-controllers.js
index 339df0a7b..04b3c29fb 100644
--- a/www/plugins/es/js/controllers/registry-controllers.js
+++ b/www/plugins/es/js/controllers/registry-controllers.js
@@ -801,7 +801,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout
       $scope.$broadcast('$recordView.enter', state);
     }
     else {
-      $state.go('app.registry_lookup');
+      $state.go('app.wot_lookup.tab_registry');
     }
   });
 
@@ -843,7 +843,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout
             $scope.loading = false;
             if (err && err.ucode === 404) {
               UIUtils.toast.show('REGISTRY.ERROR.RECORD_NOT_EXISTS');
-              $state.go('app.registry_lookup');
+              $state.go('app.wot_lookup.tab_registry');
             }
             else {
               UIUtils.onError('REGISTRY.ERROR.LOAD_RECORD_FAILED')(err);
diff --git a/www/plugins/es/js/controllers/subscription-controllers.js b/www/plugins/es/js/controllers/subscription-controllers.js
index 397bf94c6..d73f77361 100644
--- a/www/plugins/es/js/controllers/subscription-controllers.js
+++ b/www/plugins/es/js/controllers/subscription-controllers.js
@@ -68,11 +68,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet,
         return $scope.showHome();
       }
 
-      $scope.loadWallet({
-        wallet: wallet,
-        auth: true,
-        minData: true
-      })
+      wallet.auth({minData: true})
         .then(function() {
           UIUtils.loading.hide();
           return $scope.load();
@@ -81,7 +77,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet,
           $scope.showFab('fab-add-subscription-record');
         })
         .catch(function(err){
-          if (err == 'CANCELLED') {
+          if (err === 'CANCELLED') {
             UIUtils.loading.hide(10);
             $scope.loading=true; // reset for force reload next time
             $ionicHistory.goBack();
@@ -146,7 +142,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet,
         if (!cat) return;
         type = cat.id;
         // get subscription parameters
-        if (type == 'email') {
+        if (type === 'email') {
           return $scope.showEmailModal();
         }
         else {
@@ -156,7 +152,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet,
       .then(function(record) {
         if (!record) return;
         UIUtils.loading.show();
-        esSubscription.record.add(record, wallet)
+        esSubscription.record.add(record, {wallet: wallet})
           .then($scope.addToUI)
           .then(function() {
             wallet.data.subscriptions = wallet.data.subscriptions || {count: 0};
@@ -173,7 +169,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet,
     // get subscription parameters
     var promise;
     var oldRecord = angular.copy(record);
-    if (record.type == 'email') {
+    if (record.type === 'email') {
       promise = $scope.showEmailModal(record);
     }
     if (!promise) return;
@@ -185,8 +181,8 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet,
         return esSubscription.record.update(record, wallet)
           .then(function() {
             // If recipient change, update in results
-            if (oldRecord.type != record.type ||
-              oldRecord.recipient != record.recipient) {
+            if (oldRecord.type !== record.type ||
+              oldRecord.recipient !== record.recipient) {
               $scope.removeFromUI(oldRecord);
               return $scope.addToUI(record);
             }
diff --git a/www/plugins/es/js/controllers/wot-controllers.js b/www/plugins/es/js/controllers/wot-controllers.js
index 2adfdfff5..4ac6d8ed6 100644
--- a/www/plugins/es/js/controllers/wot-controllers.js
+++ b/www/plugins/es/js/controllers/wot-controllers.js
@@ -83,7 +83,7 @@ function ESWotLookupExtendController($scope, $controller, $state) {
       location: location.length ? location : undefined
     };
 
-    $state.go('app.registry_lookup', stateParams);
+    $state.go('app.wot_lookup.tab_registry', stateParams);
   };
 }
 
diff --git a/www/plugins/es/js/services/comment-services.js b/www/plugins/es/js/services/comment-services.js
index 339b3b752..374752bbe 100644
--- a/www/plugins/es/js/services/comment-services.js
+++ b/www/plugins/es/js/services/comment-services.js
@@ -167,8 +167,11 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services',
           if (index === -1) return;
           data.result.splice(index, 1);
           delete data.mapById[comment.id];
+
+          var wallet = !csWallet.isUserPubkey(comment.issuer) ? csWallet.children.getByPubkey(comment.issuer) : csWallet;
+
           // Send deletion request
-          if (csWallet.isUserPubkey(comment.issuer)) {
+          if (wallet) {
             return exports.raw.remove(comment.id)
               .catch(function(err){
                 console.error(err);
@@ -176,7 +179,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services',
               });
           }
           else {
-            return $q.reject("User is not the comment issuer");
+            return $q.reject("No wallet found corresponding to the comment issuer");
           }
         };
       };
diff --git a/www/plugins/es/js/services/document-services.js b/www/plugins/es/js/services/document-services.js
index fc58393ba..41567a054 100644
--- a/www/plugins/es/js/services/document-services.js
+++ b/www/plugins/es/js/services/document-services.js
@@ -164,19 +164,21 @@ angular.module('cesium.es.document.services', ['ngResource', 'cesium.platform',
         });
     }
 
-    function remove(document) {
+    function remove(document, options) {
       if (!document || !document.index || !document.type || !document.id) return $q.reject('Could not remove document: missing mandatory fields');
-      return esHttp.record.remove(document.index, document.type)(document.id);
+      return esHttp.record.remove(document.index, document.type)(document.id, options);
     }
 
-    function removeAll(documents) {
+    function removeAll(documents, options) {
       if (!documents || !documents.length) return;
 
-      return csWallet.auth()
-        .then(function(walletData) {
+      var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet;
+
+      return wallet.auth() // Auth once
+        .then(function() {
           // Remove each doc
           return $q.all(documents.reduce(function (res, doc) {
-            return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, walletData));
+            return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, {wallet: wallet}));
           }, []));
         });
     }
diff --git a/www/plugins/es/js/services/http-services.js b/www/plugins/es/js/services/http-services.js
index 9b0990a28..110e688d0 100644
--- a/www/plugins/es/js/services/http-services.js
+++ b/www/plugins/es/js/services/http-services.js
@@ -436,17 +436,26 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic
     function postRecord(path, options) {
       options = options || {};
       var postRequest = that.post(path);
-      return function(record, params) {
+      return function(record, options) {
+        options = options || {};
+        var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId))
+          || ((!options.pubkey || csWallet.isUserPubkey(options.pubkey)) && csWallet)
+          || (options.pubkey && csWallet.children.getByPubkey(options.pubkey));
 
-        var wallet = (params && params.wallet || csWallet);
-        params = params || {};
-        params.pubkey = params.pubkey || wallet.data.pubkey;
-        var keypair = params.keypair || wallet.data.keypair;
-        // make sure to hide some params
-        if (params) {
-          delete params.wallet;
-          delete params.keypair;
+        var keypair = options.keypair || wallet && wallet.data && wallet.data.keypair;
+
+        if (!keypair && !wallet) {
+          throw new Error('Missing wallet or keypair, to sign record')
         }
+
+        // Create the POSt request params,
+        // but BEFORE, remove protected options
+        delete options.wallet;
+        delete options.walletId;
+        delete options.keypair;
+        var params = angular.copy(options);
+        params.pubkey = params.pubkey || wallet.data.pubkey;
+
         return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true}))
           .then(function() {
             if (options.creationTime && !record.creationTime) {
@@ -499,8 +508,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic
     function removeRecord(index, type) {
       return function(id, options) {
         options = options || {};
-        var wallet = (options && options.wallet || csWallet);
-        delete options.wallet;
+        var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet;
         return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true}))
           .then(function(walletData) {
 
diff --git a/www/plugins/es/js/services/invitation-services.js b/www/plugins/es/js/services/invitation-services.js
index f10946c8f..e10117276 100644
--- a/www/plugins/es/js/services/invitation-services.js
+++ b/www/plugins/es/js/services/invitation-services.js
@@ -275,42 +275,47 @@ angular.module('cesium.es.invitation.services', ['cesium.platform',
       });
   }
 
-  function deleteInvitation(invitation) {
+  function deleteInvitation(invitation, options) {
     if (!invitation || !invitation.id) throw 'Invalid invitation (empty or without id). Could not delete.';
     var type = invitation.type || 'certification';
-    return that.raw[type].remove(invitation.id)
+    var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet;
+    return that.raw[type].remove(invitation.id, {wallet: wallet})
       .then(function() {
         // Always reset unread count
-        csWallet.data.invitations.unreadCount = 0;
+        wallet.data.invitations.unreadCount = 0;
 
-        if (!csWallet.data.invitations || !csWallet.data.invitations.list) return;
+        if (!wallet.data.invitations || !wallet.data.invitations.list) return;
 
         // Remove form list
-        csWallet.data.invitations.list.splice(csWallet.data.invitations.list.indexOf(invitation), 1);
+        wallet.data.invitations.list.splice(wallet.data.invitations.list.indexOf(invitation), 1);
       });
   }
 
-  function deleteInvitationsByIds(ids, type) {
+  function deleteInvitationsByIds(ids, type, options) {
     if (!ids || !ids.length) return $q.when();
     type = type || 'certification';
     return $q.all(
         ids.reduce(function(res, id) {
-          return res.concat(that.raw[type].remove(id));
+          return res.concat(that.raw[type].remove(id, options));
         }, [])
       );
   }
 
-  function deleteAllInvitations(pubkey, type) {
-    pubkey = pubkey || csWallet.data.pubkey;
+  function deleteAllInvitationsByPubkey(type, options) {
+
     type = type || 'certification';
 
-    console.debug('[ES] [invitation] Deleting all invitations...');
     var now = Date.now();
-    var countBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.count) || 0;
-    var unreadCountBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.unreadCount) || 0;
+    console.debug('[ES] [invitation] Deleting all {0} invitations...'.format(type));
+
+    var wallet = (options && options.pubkey && csWallet.children.getByPubkey(options.pubkey))
+      (options && options.walletId && csWallet.children.getByPubkey(options.walletId))
+      || csWallet;
+    var countBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.count) || 0;
+    var unreadCountBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.unreadCount) || 0;
 
     // Get invitation ids
-    return that.raw[type].getIds({pubkey: pubkey})
+    return that.raw[type].getIds({pubkey: wallet.data.pubkey})
       .then(function(res) {
         if (!res || !res.hits || !res.hits.total) return;
         var ids = res.hits.hits.reduce(function (res, hit) {
@@ -318,26 +323,26 @@ angular.module('cesium.es.invitation.services', ['cesium.platform',
         }, []);
 
         // Do deletion by ids
-        return deleteInvitationsByIds(ids, type)
+        return deleteInvitationsByIds(ids, type, {walletId: wallet.id})
           .then(function() {
             // Update wallet count
-            csWallet.data.invitations = csWallet.data.invitations || {};
+            wallet.data.invitations = wallet.data.invitations || {};
             // Decrement count (warning: could have received new invitations during deletion execution)
-            if (csWallet.data.invitations.count >= countBeforeDeletion) {
-              csWallet.data.invitations.count -= countBeforeDeletion || 0;
+            if (wallet.data.invitations.count >= countBeforeDeletion) {
+              wallet.data.invitations.count -= countBeforeDeletion || 0;
             }
             else {
-              csWallet.data.invitations.count = 0;
+              wallet.data.invitations.count = 0;
             }
             // Decrement count (warning: could have received new invitations during deletion execution)
-            if (csWallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) {
-              csWallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0;
+            if (wallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) {
+              wallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0;
             }
             else {
-              csWallet.data.invitations.unreadCount = 0;
+              wallet.data.invitations.unreadCount = 0;
             }
 
-            console.debug('[ES] [invitation] All invitations deleted in {0}ms'.format(Date.now()-now));
+            console.debug('[ES] [invitation] All {0} invitations deleted in {1}ms'.format(type, Date.now()-now));
           });
       });
   }
@@ -397,7 +402,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform',
   that.send = sendInvitation;
   that.delete = deleteInvitation;
   that.deleteByIds = deleteInvitationsByIds;
-  that.deleteAll = deleteAllInvitations;
+  that.deleteAll = deleteAllInvitationsByPubkey;
 
   that.constants = constants;
 
diff --git a/www/plugins/es/js/services/message-services.js b/www/plugins/es/js/services/message-services.js
index 192bb5059..c0bded686 100644
--- a/www/plugins/es/js/services/message-services.js
+++ b/www/plugins/es/js/services/message-services.js
@@ -66,8 +66,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
       console.debug('[ES] [message] Loading count...');
 
       // Count unread messages
-      countUnreadMessages(data.pubkey, csWallet)
-        .then(function(unreadCount){
+      countUnreadMessages({pubkey: data.pubkey})
+        .then(function(unreadCount) {
           data.messages = data.messages || {};
           data.messages.unreadCount = unreadCount;
           data.messages.time = time;
@@ -81,11 +81,13 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
       return deferred.promise;
     }
 
-    function countUnreadMessages(pubkey, wallet) {
-      wallet = wallet || csWallet;
-      pubkey = pubkey || (wallet.isLogin() ? wallet.data.pubkey : pubkey);
+    function countUnreadMessages(options) {
+      options = options || {};
+      var wallet = options.wallet
+        || (options.walletId && csWallet.children.get(options.walletId)) || csWallet;
+      var pubkey = options.pubkey || (wallet && wallet.data && wallet.data.pubkey);
       if (!pubkey) {
-        throw new Error('no pubkey, and user not connected.');
+        throw new Error('no pubkey or wallet found in options, and user not connected.');
       }
 
       var request = {
@@ -107,13 +109,22 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
     // Listen message changes
     function onNewMessageEvent(event, wallet) {
-      wallet = wallet || csWallet;
       console.debug("[ES] [message] detected new message (from notification service)");
 
       var notification = new EsNotification(event);
       notification.issuer = notification.pubkey;
       delete notification.pubkey;
 
+      if (!notification.issuer) return; // Skip if invalid
+
+      // Get the wallet
+      wallet = wallet || (notification.issuer && csWallet.isUserPubkey(notification.issuer) && csWallet)
+      || (notification.issuer && csWallet.children.getByPubkey(notification.issuer));
+
+      if (!wallet) {
+        throw new Error("No wallet for pubkey: {0}".format(notification.issuer.substring(0, 6)))
+      }
+
       csWot.extend(notification, 'issuer')
         .then(function() {
 
@@ -127,7 +138,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
     function sendMessage(message, options) {
       options = options || {};
-      var wallet = options.wallet || csWallet;
+      var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet;
+      delete options.wallet;
       message.issuer = message.issuer || wallet.data.pubkey;
       return wallet.getKeypair()
         .then(function(keypair) {
@@ -173,7 +185,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
       options = options || {};
       options.from = options.from || 0;
       options.size = options.size || constants.DEFAULT_LOAD_SIZE;
-      var wallet = options.wallet || csWallet;
+      var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet;
+      delete options.wallet;
 
       if (!wallet.isLogin()) {
         return $q.when([]); // Should never happen
@@ -254,7 +267,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
       options.filter = angular.isDefined(options.filter) ? options.filter : undefined;
       options.from = options.from || 0;
 
-      var wallet = options.wallet || csWallet;
+      var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet;
+      delete options.wallet; // avoid error in angular.copy()
 
       var promise = wallet.auth()
         .then(function(walletData) {
@@ -279,12 +293,15 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
           if (messages.length && options.filter){
             var filteredMessages = filterMessages(messages, options.filter);
 
-            // Recursive loop, if need more
+            // Need more messages: iterate again
             if (filteredMessages.length < messages.length) {
               options = angular.copy(options);
               options.from += options.size;
               options.size = messages.length - filteredMessages.length;
-              return loadMessages(options)
+              // put the wallet again, because it has been removed before the angular.copy()
+              // To avoid an error
+              options.wallet = wallet;
+              return loadMessages(options) // Loop
                 .then(function(messages) {
                   return filteredMessages.concat(messages);
                 });
@@ -307,20 +324,20 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
       return promise;
     }
 
-    function getAndDecrypt(id, options) {
+    function getAndDecrypt(id, type, options) {
+      var type = type || 'inbox';
       options = options || {};
-      options.type = options.type || 'inbox';
       options.summary = angular.isDefined(options.summary) ? options.summary : false/*summary not need by default*/;
-      var wallet = options.wallet || csWallet;
+      var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || csWallet;
 
       return wallet.auth()
         .then(function(walletData) {
-          return raw.getByTypeAndId({id: id, type: options.type})
+          return raw.getByTypeAndId({id: id, type: type})
             .then(function(hit) {
               if (!hit.found) return;
               var msg = hit._source;
               msg.id = hit._id;
-              msg.read = (options.type == 'outbox') || !!msg.read_signature;
+              msg.read = (type == 'outbox') || !!msg.read_signature;
               delete msg.read_signature; // not need anymore
 
               // Decrypt message
@@ -328,7 +345,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
               // Add avatar
                 .then(function(){
-                  var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient';
+                  var avatarField = (type == 'inbox') ? 'issuer' : 'recipient';
                   return csWot.extend(msg, avatarField);
                 });
             });
@@ -404,26 +421,32 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
       }
     }
 
-    function removeMessage(id, type) {
+    function removeMessage(id, type, options) {
       type = type || 'inbox';
-      return esHttp.record.remove('message', type)(id)
+
+      var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || csWallet;
+
+      return esHttp.record.remove('message', type)(id, {wallet: wallet})
         .then(function(res) {
-          // update message count
-          if (type == 'inbox') {
-            csWallet.data.messages = csWallet.data.messages || {};
-            csWallet.data.messages.count = csWallet.data.messages.count > 0 ? csWallet.data.messages.count-1 : 0;
+          // Update message count
+          if (type === 'inbox') {
+            wallet.data.messages = wallet.data.messages || {};
+            wallet.data.messages.count = wallet.data.messages.count > 0 ? wallet.data.messages.count-1 : 0;
           }
+
           // Raise event
-          api.data.raise.delete(id);
+          if (wallet.isDefault()) {
+            api.data.raise.delete(id);
+          }
 
           return res;
         });
     }
 
-    function removeAllMessages(type) {
+    function removeAllMessages(type, options) {
       type = type || 'inbox';
-
-      return csWallet.auth()
+      var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet;
+      return wallet.auth()
         .then(function(walletData) {
           // Get all message id
           return searchMessages(walletData.pubkey, {type: type, from: 0, size: 1000, _source: false})
@@ -434,7 +457,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
               // Remove each messages
               return $q.all(res.reduce(function (res, msg) {
-                return res.concat(esHttp.record.remove('message', type)(msg.id, walletData));
+                return res.concat(esHttp.record.remove('message', type)(msg.id, {wallet: wallet}));
               }, []))
                 .then(function() {
                   return ids;
@@ -442,22 +465,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
             })
             .then(function (ids) {
               // update message count
-              if (type == 'inbox') {
-                csWallet.data.messages = csWallet.data.messages || {};
-                csWallet.data.messages.count = 0;
-                csWallet.data.messages.unreadCount = 0;
+              if (type === 'inbox') {
+                wallet.data.messages = wallet.data.messages || {};
+                wallet.data.messages.count = 0;
+                wallet.data.messages.unreadCount = 0;
               }
 
               // Raise events
-              _.forEach(ids, api.data.raise.delete);
+              if (wallet.isDefault()) {
+                _.forEach(ids, api.data.raise.delete);
+              }
             });
         });
     }
 
     // Mark a message as read
     function markMessageAsRead(message, options) {
-      var type = options && options.type || 'inbox';
-      var wallet = options && options.wallet  || csWallet;
+      options = options || {};
+      var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet;
+      var type = options && options.type || (!wallet.isUserPubkey(message.recipient) ? 'outbox' : 'inbox');
       if (message.read) {
         var deferred = $q.defer();
         deferred.resolve();
@@ -479,7 +505,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
         // Update message count
         .then(function() {
-          if (type == 'inbox') {
+          if (type === 'inbox') {
             wallet.data.messages = wallet.data.messages || {};
             wallet.data.messages.unreadCount = wallet.data.messages.unreadCount ? wallet.data.messages.unreadCount - 1 : 0;
           }
@@ -488,7 +514,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
     // Mark all messages as read
     function markAllMessageAsRead(options) {
-      var wallet = options && options.wallet || csWallet;
+      options = options || {};
+      var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet;
       return wallet.auth()
         .then(function(walletData) {
 
diff --git a/www/plugins/es/js/services/subscription-services.js b/www/plugins/es/js/services/subscription-services.js
index a8924bd67..34b72c1e2 100644
--- a/www/plugins/es/js/services/subscription-services.js
+++ b/www/plugins/es/js/services/subscription-services.js
@@ -81,12 +81,12 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es
       });
   }
 
-  function addRecord(record, wallet) {
+  function addRecord(record, options) {
     if (!record || !record.type || !record.content || !record.recipient) {
       return $q.reject("Missing arguments 'record' or 'record.type' or 'record.content' or 'record.recipient'");
     }
 
-    wallet = wallet || csWallet;
+    var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet;
     var issuer = wallet.data.pubkey;
 
     var contentStr = JSON.stringify(record.content);
@@ -115,12 +115,12 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es
       ;
   }
 
-  function updateRecord(record, wallet) {
+  function updateRecord(record, options) {
     if (!record || !record.content || !record.recipient) {
       return $q.reject("Missing arguments 'record' or 'record.content', or 'record.recipient'");
     }
 
-    wallet = wallet || csWallet;
+    var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet;
     var issuer = wallet.data.pubkey;
     var contentStr = JSON.stringify(record.content);
 
diff --git a/www/plugins/es/templates/message/list.html b/www/plugins/es/templates/message/list.html
index a352f5d4c..c564a6e49 100644
--- a/www/plugins/es/templates/message/list.html
+++ b/www/plugins/es/templates/message/list.html
@@ -8,8 +8,8 @@
 
   <ion-item
     class="item item-border-large item-avatar item-icon-right ink"
-    ng-repeat="msg in search.results"
-    ng-click="select(msg)">
+    ng-repeat="msg in :rebind:search.results track by msg.id"
+    ng-click="select(msg, $event)">
 
     <i ng-if="::!msg.avatar" class="item-image icon" ng-class="{'ion-person': msg.uid, 'ion-email': !msg.uid}"></i>
     <i ng-if="::msg.avatar" class="item-image avatar" style="background-image: url({{::msg.avatar.src}})"></i>
diff --git a/www/plugins/es/templates/message/lookup_by_id.html b/www/plugins/es/templates/message/lookup_by_id.html
new file mode 100644
index 000000000..cdf3578f4
--- /dev/null
+++ b/www/plugins/es/templates/message/lookup_by_id.html
@@ -0,0 +1,17 @@
+<ion-view left-buttons="leftButtons" class="view-messages">
+
+  <ion-tabs class="tabs-positive tabs-icon-top">
+
+    <ion-tab title="{{'MESSAGE.LIST.INBOX'|translate}}" icon="ion-archive"
+      ui-sref="app.user_messages_by_id.tab_inbox">
+      <ion-nav-view name="tab_inbox"></ion-nav-view>
+    </ion-tab>
+
+    <ion-tab title="{{'MESSAGE.LIST.OUTBOX'|translate}}" icon="ion-paper-airplane"
+             ui-sref="app.user_messages_by_id.tab_outbox">
+      <ion-nav-view name="tab_outbox"></ion-nav-view>
+    </ion-tab>
+
+  </ion-tabs>
+
+</ion-view>
diff --git a/www/plugins/es/templates/message/lookup_lg.html b/www/plugins/es/templates/message/lookup_lg.html
index 70db4c64b..66349decf 100644
--- a/www/plugins/es/templates/message/lookup_lg.html
+++ b/www/plugins/es/templates/message/lookup_lg.html
@@ -12,7 +12,7 @@
 
   <ion-content class="padding no-padding-xs no-padding-sm">
     <ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}"
-                   on-refresh="refresh(true)">
+                   on-refresh="refresh(true, $event)">
     </ion-refresher>
 
     <!-- Buttons bar-->
@@ -37,16 +37,32 @@
     <!-- button tabs -->
     <div class="buttons-tabs border-bottom hidden-sm hidden-xs">
       <div class="pull-right">
-        <div
-          class="button button-tab dark"
+
+        <!-- inbox tab -->
+        <a
+          ng-hide="!isDefaultWallet"
+          class="button button-tab ink dark"
           title="{{'MESSAGE.LIST.INBOX' | translate}}"
           nav-transition="none"
           ng-class="{'active': type=='inbox'}"
           ui-sref="app.user_messages_lg_inbox">
           <i class="icon ion-archive"></i>
           {{'MESSAGE.LIST.INBOX' | translate}}
-        </div>
+        </a>
+        <a
+          ng-hide="isDefaultWallet"
+          class="button button-tab ink dark"
+          title="{{'MESSAGE.LIST.INBOX' | translate}}"
+          nav-transition="none"
+          ng-class="{'active': type=='inbox'}"
+          ui-sref="app.user_messages_lg_inbox_by_id({id: walletId})">
+          <i class="icon ion-archive"></i>
+          {{'MESSAGE.LIST.INBOX' | translate}}
+        </a>
+
+        <!-- outbox tab -->
         <a
+          ng-hide="!isDefaultWallet"
           class="button button-tab ink dark"
           title="{{'MESSAGE.LIST.OUTBOX' | translate}}"
           nav-transition="none"
@@ -55,6 +71,16 @@
           <i class="icon ion-paper-airplane"></i>
           {{'MESSAGE.LIST.OUTBOX' | translate}}
         </a>
+        <a
+          ng-hide="isDefaultWallet"
+          class="button button-tab ink dark"
+          title="{{'MESSAGE.LIST.OUTBOX' | translate}}"
+          nav-transition="none"
+          ng-class="{'active': type=='outbox'}"
+          ui-sref="app.user_messages_lg_outbox_by_id({id: walletId})">
+          <i class="icon ion-paper-airplane"></i>
+          {{'MESSAGE.LIST.OUTBOX' | translate}}
+        </a>
       </div>
     </div>
 
diff --git a/www/plugins/es/templates/message/popover_message.html b/www/plugins/es/templates/message/popover_message.html
index 31ed03406..2155e2031 100644
--- a/www/plugins/es/templates/message/popover_message.html
+++ b/www/plugins/es/templates/message/popover_message.html
@@ -1,4 +1,4 @@
-<ion-popover-view class="fit hidden-xs hidden-sm popover-notification"
+<ion-popover-view class="fit hidden-xs hidden-sm popover-light"
                   ng-controller="PopoverMessageCtrl">
   <ion-header-bar class="stable-bg block">
     <div class="title" translate>MESSAGE.NOTIFICATIONS.TITLE</div>
diff --git a/www/templates/wallet/list/item_wallet_light.html b/www/templates/wallet/list/item_wallet_light.html
index b8882d564..610ca609a 100644
--- a/www/templates/wallet/list/item_wallet_light.html
+++ b/www/templates/wallet/list/item_wallet_light.html
@@ -4,7 +4,7 @@
      ng-init="walletData=wallet.data;">
 
   <i ng-if="::!walletData.avatar" class="item-image icon"
-     ng-class=":rebind:{'ion-card': !walletData.isMember, 'ion-persion': walletData.isMember}"></i>
+     ng-class="::{'ion-card': !walletData.isMember, 'ion-person': walletData.isMember}"></i>
   <i ng-if="::walletData.avatar" class="item-image avatar" style="background-image: url({{::walletData.avatar.src}})"></i>
   <div class="badge badge-button badge-avatar badge-assertive ion-locked " ng-hide="::wallet.isAuth()">
   </div>
diff --git a/www/templates/wallet/list/popover_wallets.html b/www/templates/wallet/list/popover_wallets.html
index 080071a94..458d603b4 100644
--- a/www/templates/wallet/list/popover_wallets.html
+++ b/www/templates/wallet/list/popover_wallets.html
@@ -1,7 +1,12 @@
-<ion-popover-view class="fit popover-wallets"
-                  ng-controller="PopoverWalletSelectModalCtrl">
-  <ion-header-bar>
-    <h1 class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</h1>
+<ion-popover-view class="fit popover-wallets popover-light">
+  <ion-header-bar class="stable-bg block">
+    <div class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</div>
+
+    <div class="pull-right">
+      <a class="positive"
+         ng-click="showNewWalletModal()"
+         translate>ACCOUNT.WALLET_LIST.BTN_NEW</a>
+    </div>
   </ion-header-bar>
   <ion-content scroll="true">
 
@@ -9,15 +14,30 @@
       <ion-spinner icon="android"></ion-spinner>
     </div>
 
-    <div class="center padding gray" ng-if="!loading && !wallets.length">
+    <div class="center padding gray" ng-if="!loading && !wallets.length && !defaultWallet">
       {{:locale:'ACCOUNT.WALLET_LIST.NO_WALLET'|translate}}
     </div>
 
     <ion-list ng-if="!loading">
-      <ng-repeat ng-repeat="wallet in wallets track by wallet.id"
+
+      <ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="'templates/wallet/list/item_wallet_light.html'">
+      </ng-include>
+
+      <ng-repeat ng-repeat="wallet in :rebind:wallets | filter:filterFn(formData) track by wallet.id"
                  ng-include="'templates/wallet/list/item_wallet_light.html'">
 
       </ng-repeat>
     </ion-list>
   </ion-content>
+
+  <ion-footer-bar class="stable-bg block">
+
+    <!-- show all -->
+    <div class="pull-right">
+      <a class="positive"
+         ui-sref="app.view_wallets"
+         ng-click="closePopover()"
+         translate>COMMON.NOTIFICATIONS.SHOW_ALL</a>
+    </div>
+  </ion-footer-bar>
 </ion-popover-view>
diff --git a/www/templates/wallet/list/view_wallets.html b/www/templates/wallet/list/view_wallets.html
index e0eb1e166..b92075b1e 100644
--- a/www/templates/wallet/list/view_wallets.html
+++ b/www/templates/wallet/list/view_wallets.html
@@ -62,9 +62,12 @@
     </div>
 
     <ion-list class="{{::motion.ionListClass}}">
+
+      <!-- default wallet -->
       <ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="'templates/wallet/list/item_wallet.html'">
       </ng-include>
 
+      <!-- children wallets -->
       <ng-include ng-repeat="wallet in wallets track by wallet.id"
                  src="'templates/wallet/list/item_wallet.html'">
       </ng-include>
diff --git a/www/templates/wallet/view_wallet.html b/www/templates/wallet/view_wallet.html
index abdd5b998..6825e9292 100644
--- a/www/templates/wallet/view_wallet.html
+++ b/www/templates/wallet/view_wallet.html
@@ -25,16 +25,31 @@
          ng-class="{'hero-qrcode-active': toggleQRCode}">
       <div class="content" ng-if="!loading">
 
+
         <i class="avatar"
            ng-if=":rebind:!formData.avatar"
            ng-class=":rebind:{'avatar-wallet': !formData.isMember, 'avatar-member': formData.isMember}"></i>
         <i class="avatar"
            ng-if=":rebind:formData.avatar"
            style="background-image: url({{:rebind:formData.avatar.src}})"></i>
+
         <h3 class="light">
-          <ng-if ng-if=":rebind:formData.name">{{:rebind:formData.name}}</ng-if>
-          <ng-if ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</ng-if>
-          <ng-if ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</ng-if>
+          <ng-if ng-if=":rebind:!enableSelectWallet">
+            <span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span>
+            <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span>
+            <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span>
+          </ng-if>
+          <!-- select wallet button -->
+          <a ng-if=":rebind:enableSelectWallet"
+             class="hidden-xs hidden-sm"
+             style="color: lightgray;"
+             title="{{:locale:'ACCOUNT.SELECT_WALLET_MODAL.TITLE'|translate}}"
+             ng-click="showSelectWalletPopover($event)">
+            <span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span>
+            <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span>
+            <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span>
+            <i class="ion-arrow-down-b"></i>
+          </a>
         </h3>
 
         <h4 class="assertive"><ng-if ng-if=":rebind:(formData.name || formData.uid) && !formData.isMember" translate>WOT.NOT_MEMBER_PARENTHESIS</ng-if></h4>
diff --git a/www/templates/wot/view_identity.html b/www/templates/wot/view_identity.html
index 8e820bc95..4147fbb3b 100644
--- a/www/templates/wot/view_identity.html
+++ b/www/templates/wot/view_identity.html
@@ -10,7 +10,7 @@
                    on-refresh="doUpdate(true)">
     </ion-refresher>
 
-    <div class="hero">
+    <div class="hero" ng-class="{'hero-qrcode-active': toggleQRCode}">
       <div class="content" ng-if="!loading">
         <i class="avatar"
            ng-if=":rebind:!formData.avatar"
-- 
GitLab