diff --git a/.gitignore b/.gitignore
index c31fbcdc2c5c74f2ed9dbffeb26b27e630361cb8..dad43d5c42eb92672d82f08c4f81dd3c08b1647c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,6 @@
 node_modules/
 platforms/
 plugins/
-.idea/
\ No newline at end of file
+.idea/
+cesium.iml
+pom.xml
\ No newline at end of file
diff --git a/www/index.html b/www/index.html
index 32d7cbdc6c7c675a71d109b3c149f97caec71c0b..eb0d15a85c8a49e7e65cfd2ec1d6fa6a6cc2a096 100644
--- a/www/index.html
+++ b/www/index.html
@@ -29,13 +29,27 @@
     <!-- cordova script (this will be a 404 during development) -->
     <script src="cordova.js"></script>
 
-    <!-- your app's js -->
-    <script src="js/app.js"></script>
+    <!-- services -->
+    <script src="js/services/crypto-services.js"></script>
+    <script src="js/services/utils-services.js"></script>
+    <script src="js/services/wallet-services.js"></script>
+    <script src="js/services/bma-services.js"></script>
+
+    <!-- entities -->
     <script src="js/entity/peer.js"></script>
-    <script src="js/controllers/peer_controller.js"></script>
-    <script src="js/home-controller.js"></script>
-    <script src="js/explore-controller.js"></script>
+
+    <!-- controllers -->
+    <script src="js/controllers/home-controllers.js"></script>
+    <script src="js/controllers/wot-controllers.js"></script>
+    <script src="js/controllers/peer-controllers.js"></script>
+    <script src="js/controllers/currency-controllers.js"></script>
+    <script src="js/controllers/wallet-controllers.js"></script>
+
+    <!-- App -->
+    <script src="js/app.js"></script>
     <script src="js/services.js"></script>
+    <script src="js/controllers.js"></script>
+
   </head>
   <body ng-app="cesium">
     <ion-nav-view></ion-nav-view>
diff --git a/www/js/app.js b/www/js/app.js
index 856f0649a19f118db2debccea43b4ba7d388ca74..bc9ab915a74ef33df27aa93732c1356a82325485 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -58,87 +58,5 @@ angular.module('cesium', ['ionic', 'cesium.controllers'])
   });
 })
 
-.config(function($stateProvider, $urlRouterProvider) {
-  $stateProvider
 
-    .state('app', {
-      url: "/app",
-      abstract: true,
-      templateUrl: "templates/menu.html",
-      controller: 'HomeCtrl'
-    })
-
-    .state('app.home', {
-      url: "/home",
-      views: {
-        'menuContent': {
-          templateUrl: "templates/home.html",
-          controller: 'HomeCtrl'
-        }
-      }
-    })
-
-    .state('app.explore_currency', {
-      url: "/home/explore",
-      views: {
-        'menuContent': {
-          templateUrl: "templates/explore/explore_currency.html",
-          controller: 'CurrenciesCtrl'
-        }
-      }
-    })
-
-    .state('app.explore_tabs', {
-      url: "/currency",
-      views: {
-        'menuContent': {
-          templateUrl: "templates/explore/explore_tabs.html",
-          controller: 'ExploreCtrl'
-        }
-      }
-    })
-
-    .state('app.view_peer', {
-      url: "/peer/:server",
-      views: {
-        'menuContent': {
-          templateUrl: "templates/explore/view_peer.html",
-          controller: 'PeerCtrl'
-        }
-      }
-    })
-
-    .state('app.view_identity', {
-      url: "/wot/:pub",
-      views: {
-        'menuContent': {
-          templateUrl: "templates/wot/view_identity.html",
-          controller: 'IdentityCtrl'
-        }
-      }
-    })
-
-    .state('app.view_wallet', {
-      url: "/wallet",
-      views: {
-        'menuContent': {
-          templateUrl: "templates/account/view_wallet.html",
-          controller: 'WalletCtrl'
-        }
-      }
-    })
-
-    .state('app.view_transfer', {
-      url: "/transfer/:pubkey/:uid",
-      views: {
-        'menuContent': {
-          templateUrl: "templates/account/view_transfer.html",
-          controller: 'TransferCtrl'
-        }
-      }
-    });
-
-  // if none of the above states are matched, use this as the fallback
-  $urlRouterProvider.otherwise('/app/home');
-})
 ;
diff --git a/www/js/controllers.js b/www/js/controllers.js
new file mode 100644
index 0000000000000000000000000000000000000000..0d217aaafe891f05ccaee098e1a8cec11a7da1bb
--- /dev/null
+++ b/www/js/controllers.js
@@ -0,0 +1,16 @@
+
+angular.module('cesium.controllers', [
+    'cesium.home.controllers',
+    'cesium.wallet.controllers',
+    'cesium.currency.controllers',
+    'cesium.wot.controllers'
+  ])
+
+  .config(function($httpProvider) {
+    //Enable cross domain calls
+   $httpProvider.defaults.useXDomain = true;
+
+    //Remove the header used to identify ajax call  that would prevent CORS from working
+    delete $httpProvider.defaults.headers.common['X-Requested-With'];
+  })
+;
diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js
new file mode 100644
index 0000000000000000000000000000000000000000..d8989dbaaf86b494701f1e6c22bb65e4c7aa979f
--- /dev/null
+++ b/www/js/controllers/currency-controllers.js
@@ -0,0 +1,305 @@
+
+angular.module('cesium.currency.controllers', ['cesium.services'])
+
+.config(function($stateProvider, $urlRouterProvider) {
+  $stateProvider
+
+    .state('app.explore_currency', {
+      url: "/home/explore",
+      views: {
+        'menuContent': {
+          templateUrl: "templates/explore/explore_currency.html",
+          controller: 'CurrenciesCtrl'
+        }
+      }
+    })
+
+    .state('app.explore_tabs', {
+      url: "/currency",
+      views: {
+        'menuContent': {
+          templateUrl: "templates/explore/explore_tabs.html",
+          controller: 'ExploreCtrl'
+        }
+      }
+    })
+
+    .state('app.view_peer', {
+      url: "/peer/:server",
+      views: {
+        'menuContent': {
+          templateUrl: "templates/explore/view_peer.html",
+          controller: 'PeerCtrl'
+        }
+      }
+    })
+})
+
+.controller('CurrenciesCtrl', CurrenciesController)
+
+.controller('ExploreCtrl', ExploreController)
+
+.controller('PeerCtrl', PeerController)
+
+;
+
+function CurrenciesController($scope, $state) {
+
+  $scope.selectedCurrency = '';
+  $scope.knownCurrencies = ['meta_brouzouf'];
+
+  // Called to navigate to the main app
+  $scope.selectCurrency = function(currency) {
+    $scope.selectedCurrency = currency;
+    $state.go('app.explore_tabs');
+  };
+}
+
+function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interval, $timeout) {
+
+  var USE_RELATIVE_DEFAULT = true;
+
+  CurrenciesController.call(this, $scope, $state);
+  WotLookupController.call(this, $scope, BMA, $state);
+  PeersController.call(this, $scope, $rootScope, BMA, UIUtils, $q, $interval, $timeout);
+
+  $scope.accountTypeMember = null;
+  $scope.accounts = [];
+  $scope.search = { text: '', results: {} };
+  $scope.knownCurrencies = ['meta_brouzouf'];
+  $scope.formData = { useRelative: false };
+  $scope.knownBlocks = [];
+  $scope.entered = false;
+
+  $scope.$on('$ionicView.enter', function(e, $state) {
+    if (!$scope.entered) {
+      $scope.entered = true;
+      $scope.startListeningOnSocket();
+    }
+    $timeout(function() {
+      if ((!$scope.search.peers || $scope.search.peers.length == 0) && $scope.search.lookingForPeers){
+        $scope.updateExploreView();
+      }
+    }, 2000);
+  });
+
+  $scope.startListeningOnSocket = function() {
+
+    // Currency OK
+    BMA.websocket.block().on('block', function(block) {
+      var theFPR = fpr(block);
+      if ($scope.knownBlocks.indexOf(theFPR) === -1) {
+        $scope.knownBlocks.push(theFPR);
+        // We wait 2s when a new block is received, just to wait for network propagation
+        var wait = $scope.knownBlocks.length === 1 ? 0 : 2000;
+        $timeout(function() {
+          $scope.updateExploreView();
+        }, wait);
+      }
+    });
+    BMA.websocket.peer().on('peer', function(peer) {
+      console.log(peer);
+    });
+  };
+
+  $scope.$watch('formData.useRelative', function() {
+    if ($scope.formData.useRelative) {
+      $scope.M = $scope.M / $scope.currentUD;
+      $scope.MoverN = $scope.MoverN / $scope.currentUD;
+      $scope.UD = $scope.UD / $scope.currentUD;
+      $scope.unit = 'universal_dividend';
+      $scope.udUnit = $scope.baseUnit;
+    } else {
+      $scope.M = $scope.M * $scope.currentUD;
+      $scope.MoverN = $scope.MoverN * $scope.currentUD;
+      $scope.UD = $scope.UD * $scope.currentUD;
+      $scope.unit = $scope.baseUnit;
+      $scope.udUnit = '';
+    }
+  }, true);
+
+  $scope.doUpdate = function() {
+    $scope.updateExploreView();
+  };
+
+  $scope.updateExploreView = function() {
+
+    UIUtils.loading.show();
+    $scope.formData.useRelative = false;
+
+    $q.all([
+
+      // Get the currency parameters
+      BMA.currency.parameters()
+        .then(function(json){
+          $scope.c = json.c;
+          $scope.baseUnit = json.currency;
+          $scope.unit = json.currency;
+        }),
+
+      // Get the current block informations
+      BMA.blockchain.current()
+        .then(function(block){
+          $scope.M = block.monetaryMass;
+          $scope.N = block.membersCount;
+          $scope.time  = moment(block.medianTime*1000).format('YYYY-MM-DD HH:mm');
+          $scope.difficulty  = block.powMin;
+        }),
+
+      // Get the UD informations
+      BMA.blockchain.stats.ud()
+        .then(function(res){
+          if (res.result.blocks.length) {
+            var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1];
+            return BMA.blockchain.block({ block: lastBlockWithUD })
+              .then(function(block){
+                $scope.currentUD = block.dividend;
+                $scope.UD = block.dividend;
+                $scope.Nprev = block.membersCount;
+              });
+          }
+        })
+    ])
+
+      // Done
+      .then(function(){
+        $scope.M = $scope.M - $scope.UD*$scope.Nprev;
+        $scope.MoverN = $scope.M / $scope.Nprev;
+        $scope.cactual = 100 * $scope.UD / $scope.MoverN;
+        $scope.formData.useRelative = USE_RELATIVE_DEFAULT;
+        UIUtils.loading.hide();
+      })
+      .catch(function(err) {
+        console.error('>>>>>>>' , err);
+        UIUtils.alert.error('Could not fetch informations from remote uCoin node.');
+        UIUtils.loading.hide();
+      })
+      .then(function(){
+        // Network
+        $scope.searchPeers();
+      });
+  };
+}
+
+
+function PeersController($scope, $rootScope, BMA, UIUtils, $q, $interval, $timeout) {
+
+  var newPeers = [], interval, lookingForPeers;
+  $scope.search.lookingForPeers = false;
+  $scope.search.peers = [];
+
+  $scope.overviewPeers = function() {
+    var currents = {}, block;
+    for (var i = 0, len = $scope.search.peers.length; i < len; i++) {
+      block = $scope.search.peers[i].current;
+      if (block) {
+        var bid = fpr(block);
+        currents[bid] = currents[bid] || 0;
+        currents[bid]++;
+      }
+    }
+    var fprs = _.keys(currents).map(function(key) {
+      return { fpr: key, qty: currents[key] };
+    });
+    var best = _.max(fprs, function(obj) {
+      return obj.qty;
+    });
+    var p;
+    for (var j = 0, len2 = $scope.search.peers.length; j < len2; j++) {
+      p = $scope.search.peers[j];
+      p.hasMainConsensusBlock = fpr(p.current) == best.fpr;
+      p.hasConsensusBlock = !p.hasMainConsensusBlock && currents[fpr(p.current)] > 1;
+    }
+    $scope.search.peers = _.uniq($scope.search.peers, false, function(peer) {
+      return peer.pubkey;
+    });
+    $scope.search.peers = _.sortBy($scope.search.peers, function(p) {
+      var score = 1
+        + 10000 * (p.online ? 1 : 0)
+        + 1000  * (p.hasMainConsensusBlock ? 1 : 0) +
+        + 100   * (p.uid ? 1 : 0);
+      return -score;
+    });
+  };
+
+  $scope.searchPeers = function() {
+
+    if (interval) {
+      $interval.cancel(interval);
+    }
+
+    interval = $interval(function() {
+      if (newPeers.length) {
+        $scope.search.peers = $scope.search.peers.concat(newPeers.splice(0));
+        $scope.overviewPeers();
+      } else if (lookingForPeers && !$scope.search.lookingForPeers) {
+        // The peer lookup endend, we can make a clean final report
+        $timeout(function(){
+          lookingForPeers = false;
+          $scope.overviewPeers();
+        }, 1000);
+      }
+    }, 1000);
+
+    var known = {};
+    $rootScope.members = [];
+    $scope.search.peers = [];
+    $scope.search.lookingForPeers = true;
+    lookingForPeers = true;
+    return BMA.network.peering.peers({ leaves: true })
+      .then(function(res){
+        return BMA.wot.members()
+          .then(function(json){
+            $rootScope.members = json.results;
+            return res;
+          });
+      })
+      .then(function(res){
+        return $q.all(res.leaves.map(function(leaf) {
+          return BMA.network.peering.peers({ leaf: leaf })
+            .then(function(subres){
+              var peer = subres.leaf.value;
+              if (peer) {
+                peer = new Peer(peer);
+                // Test each peer only once
+                if (!known[peer.getURL()]) {
+                  peer.dns = peer.getDns();
+                  peer.blockNumber = peer.block.replace(/-.+$/, '');
+                  var member = _.findWhere($rootScope.members, { pubkey: peer.pubkey });
+                  peer.uid = member && member.uid;
+                  newPeers.push(peer);
+                  var node = BMA.instance(peer.getURL());
+                  return node.blockchain.current()
+                    .then(function(block){
+                      peer.current = block;
+                      peer.online = true;
+                      peer.server = peer.getURL();
+                      if ($scope.knownBlocks.indexOf(fpr(block)) === -1) {
+                        $scope.knownBlocks.push(fpr(block));
+                      }
+                    })
+                    .catch(function(err) {
+                    })
+                }
+              }
+            })
+        }))
+          .then(function(){
+            $scope.search.lookingForPeers = false;
+          })
+      })
+      .catch(function(err) {
+        //console.log(err);
+        //UIUtils.alert.error('Could get peers from remote uCoin node.');
+        //$scope.search.lookingForPeers = false;
+      });
+  };
+
+  $scope.viewPeer = function() {
+
+  };
+}
+
+function fpr(block) {
+  return block && [block.number, block.hash].join('-');
+}
diff --git a/www/js/controllers/home-controllers.js b/www/js/controllers/home-controllers.js
new file mode 100644
index 0000000000000000000000000000000000000000..5a55420b159970654e113c708afe20daced71b58
--- /dev/null
+++ b/www/js/controllers/home-controllers.js
@@ -0,0 +1,263 @@
+
+angular.module('cesium.home.controllers', ['cesium.services'])
+
+  .config(function($httpProvider) {
+    //Enable cross domain calls
+   $httpProvider.defaults.useXDomain = true;
+
+    //Remove the header used to identify ajax call  that would prevent CORS from working
+    delete $httpProvider.defaults.headers.common['X-Requested-With'];
+  })
+
+  .controller('HomeCtrl', HomeController)
+
+  .config(function($stateProvider, $urlRouterProvider) {
+    $stateProvider
+
+      .state('app', {
+        url: "/app",
+        abstract: true,
+        templateUrl: "templates/menu.html",
+        controller: 'HomeCtrl'
+      })
+
+      .state('app.home', {
+        url: "/home",
+        views: {
+          'menuContent': {
+            templateUrl: "templates/home.html",
+            controller: 'HomeCtrl'
+          }
+        }
+      })
+
+    // if none of the above states are matched, use this as the fallback
+    $urlRouterProvider.otherwise('/app/home');
+  })
+;
+
+function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate) {
+  // Form data for the login modal
+  $scope.loginData = {
+    username: null,
+    password: null
+  };
+
+  // Login modal
+  $scope.loginModal = "undefined";
+
+  // Create the login modal that we will use later
+  $ionicModal.fromTemplateUrl('templates/login.html', {
+    scope: $scope,
+    focusFirstInput: true
+  }).then(function(modal) {
+    $scope.loginModal = modal;
+    $scope.loginModal.hide();
+  });
+
+  // Open login modal
+  $scope.login = function(callback) {
+    if ($scope.loginModal != "undefined" && $scope.loginModal != null) {
+      $scope.loginModal.show();
+      $scope.loginData.callback = callback;
+    }
+    else{
+      $timeout($scope.login, 2000);
+    }    
+  };
+
+  // Login and load wallet
+  $scope.loadWallet = function() {
+    return $q(function(resolve, reject){
+      if (!Wallet.isLogin()) {
+        $scope.login(function() {
+          Wallet.loadData()
+            .then(function(walletData){
+              resolve(walletData);
+            })
+            .catch(function(err) {
+              console.error('>>>>>>>' , err);
+              UIUtils.alert.error('Your browser is not compatible with cryptographic features.');
+              UIUtils.loading.hide();
+              reject(err);
+            });
+        });
+      }
+      else if (!Wallet.data.loaded) {
+        Wallet.loadData()
+          .then(function(walletData){
+            resolve(walletData);
+          })
+          .catch(function(err) {
+            console.error('>>>>>>>' , err);
+            UIUtils.alert.error('Could not fetch wallet data from remote uCoin node.');
+            UIUtils.loading.hide();
+            reject(err);
+          });
+      }
+      else {
+        resolve(Wallet.data);
+      }
+    });
+  };
+
+  // Triggered in the login modal to close it
+  $scope.closeLogin = function() {
+    return $scope.loginModal.hide();
+  };
+
+  // Login form submit
+  $scope.doLogin = function() {
+    $scope.closeLogin();
+    UIUtils.loading.show(); 
+
+    // Call wallet login
+    Wallet.login($scope.loginData.username, $scope.loginData.password)
+    .catch(function(err) {
+      $scope.loginData = {}; // Reset login data
+      UIUtils.loading.hide();
+      console.error('>>>>>>>' , err);
+      UIUtils.alert.error('Your browser is not compatible with cryptographic libraries.');
+    })
+    .then(function(){
+      UIUtils.loading.hide();
+      var callback = $scope.loginData.callback;
+      $scope.loginData = {}; // Reset login data
+      if (callback != "undefined" && callback != null) {
+        callback();
+      }
+      // Default: redirect to wallet view
+      else {
+        $state.go('app.view_wallet');
+      }
+    });
+  };
+
+  $scope.loginDataChanged = function() {
+    $scope.loginData.computing=false;
+    $scope.loginData.pubkey=null;
+  };
+
+  $scope.showLoginPubkey = function() {
+    $scope.loginData.computing=true;
+    CryptoUtils.connect($scope.loginData.username, $scope.loginData.password).then(
+        function(keypair) {
+            $scope.loginData.pubkey = CryptoUtils.util.encode_base58(keypair.signPk);
+            $scope.loginData.computing=false;
+        }
+    )
+    .catch(function(err) {
+      $scope.loginData.computing=false;
+      UIUtils.loading.hide();
+      console.error('>>>>>>>' , err);
+      UIUtils.alert.error('Your browser is not compatible with cryptographic libraries.');
+    });
+  };
+
+  // Logout
+  $scope.logout = function() {
+    UIUtils.loading.show();
+    Wallet.logout().then(
+        function() {
+          UIUtils.loading.hide();
+          $ionicSideMenuDelegate.toggleLeft();
+          $state.go('app.home');
+        }
+    );
+  };
+
+  // Is connected
+  $scope.isLogged = function() {
+      return Wallet.isLogin();
+  };
+
+  // Is not connected
+  $scope.isNotLogged = function() {
+    return !Wallet.isLogin();
+  };
+}
+
+function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA, UIUtils, $q, $timeout, Wallet, CryptoUtils, $ionicSideMenuDelegate) {
+
+  // With the new view caching in Ionic, Controllers are only called
+  // when they are recreated or on app start, instead of every page change.
+  // To listen for when this page is active (for example, to refresh data),
+  // listen for the $ionicView.enter event:
+  //$scope.$on('$ionicView.enter', function(e) {
+  //});
+
+  //CurrenciesController.call(this, $scope, $state);
+  //LookupController.call(this, $scope, BMA, $state);
+  LoginController.call(this, $scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate);
+
+  $scope.accountTypeMember = null;
+  $scope.accounts = [];
+  $scope.search = { text: '', results: {} };
+  $scope.knownCurrencies = ['meta_brouzouf'];
+
+  // Called to navigate to the main app
+  $scope.cancel = function() {
+    $scope.modal.hide();
+    $timeout(function(){
+      $scope.selectedCurrency = '';
+      $scope.accountTypeMember = null;
+      $scope.search.text = '';
+      $scope.search.results = [];
+    }, 200);
+  };
+
+  $scope.$on('currencySelected', function() {
+    $ionicSlideBoxDelegate.slide(1);
+  });
+
+  $scope.selectAccountTypeMember = function(bool) {
+    $scope.accountTypeMember = bool;
+    $ionicSlideBoxDelegate.slide(2);
+  };
+
+  $scope.next = function() {
+    $ionicSlideBoxDelegate.next();
+  };
+  $scope.previous = function() {
+    $ionicSlideBoxDelegate.previous();
+  };
+
+  // Called each time the slide changes
+  $scope.slideChanged = function(index) {
+    $scope.slideIndex = index;
+    $scope.nextStep = $scope.slideIndex == 2 ? 'Start using MyApp' : 'Next';
+  };
+
+  $scope.addAccount = function() {
+    $scope.modal.show();
+    $scope.slideChanged(0);
+    $ionicSlideBoxDelegate.slide(0);
+    $ionicSlideBoxDelegate.enableSlide(false);
+    // TODO: remove default
+    //$timeout(function() {
+    //  $scope.selectedCurrency = $scope.knownCurrencies[0];
+    //  $scope.accountTypeMember = true;
+    //  $scope.searchChanged();
+    //  $scope.search.text = 'cgeek';
+    //  $ionicSlideBoxDelegate.next();
+    //  $ionicSlideBoxDelegate.next();
+    //}, 300);
+  };
+
+  // Create the account modal that we will use later
+  $ionicModal.fromTemplateUrl('templates/account/new_account.html', {
+    scope: $scope
+  }).then(function(modal) {
+    $scope.modal = modal;
+    $scope.modal.hide();
+    // TODO: remove auto add account when done
+    //$timeout(function() {
+    //  $scope.addAccount();
+    //}, 400);
+  });
+
+  $scope.selectCurrency = function(currency) {
+    $scope.selectedCurrency = currency;
+    $scope.next();
+  }
+}
diff --git a/www/js/controllers/peer_controller.js b/www/js/controllers/peer-controllers.js
similarity index 100%
rename from www/js/controllers/peer_controller.js
rename to www/js/controllers/peer-controllers.js
diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js
new file mode 100644
index 0000000000000000000000000000000000000000..b7e91e9b6871c4c46b9c2b221faec8f9c3133acb
--- /dev/null
+++ b/www/js/controllers/wallet-controllers.js
@@ -0,0 +1,225 @@
+
+angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency.controllers'])
+
+  .config(function($stateProvider, $urlRouterProvider) {
+    $stateProvider
+
+      .state('app.view_wallet', {
+        url: "/wallet",
+        views: {
+          'menuContent': {
+            templateUrl: "templates/account/view_wallet.html",
+            controller: 'WalletCtrl'
+          }
+        }
+      })
+
+      .state('app.view_transfer_uid', {
+        url: "/transfer/:pubkey/:uid",
+        views: {
+          'menuContent': {
+            templateUrl: "templates/account/view_transfer.html",
+            controller: 'TransferCtrl'
+          }
+        }
+      })
+
+      .state('app.view_transfer_pubkey', {
+        url: "/transfer/:pubkey",
+        views: {
+          'menuContent': {
+            templateUrl: "templates/account/view_transfer.html",
+            controller: 'TransferCtrl'
+          }
+        }
+      })
+    ;
+  })
+
+  .controller('WalletCtrl', WalletController)
+
+  .controller('TransferCtrl', TransferController)
+;
+
+function WalletController($scope, $state, $q, $ionicPopup, UIUtils, Wallet) {
+
+  $scope.walletData = {};
+  $scope.convertedBalance = 0;
+  $scope.hasCredit = false;
+  $scope.isMember = false;
+
+  $scope.$on('$ionicView.enter', function(e, $state) {
+    $scope.loadWallet()
+      .then(function(wallet) {
+        $scope.updateWalletView(wallet);
+      });
+  });
+
+  $scope.refreshConvertedBalance = function() {
+    if ($scope.walletData.useRelative) {
+      $scope.convertedBalance = $scope.walletData.balance / $scope.walletData.currentUD;
+      $scope.unit = 'universal_dividend';
+      $scope.udUnit = $scope.walletData.currency;
+    } else {
+      $scope.convertedBalance = $scope.walletData.balance;
+      $scope.unit = $scope.walletData.currency;
+      $scope.udUnit = '';
+    }
+  };
+  $scope.$watch('walletData.useRelative', $scope.refreshConvertedBalance, true);
+  $scope.$watch('walletData.balance', $scope.refreshConvertedBalance, true);
+
+  // Update view
+  $scope.updateWalletView = function(wallet) {
+    $scope.walletData = wallet;
+    $scope.hasCredit = ($scope.walletData.balance != "undefined" && $scope.walletData.balance > 0);
+    $scope.isMember = ($scope.walletData.requirements != "undefined" && $scope.walletData.requirements != null
+                      && $scope.walletData.requirements.uid != "undefined" && $scope.walletData.requirements.uid != null);
+  };
+
+  // Has credit
+  $scope.hasCredit= function() {
+    return $scope.balance > 0;
+  };
+
+  // Transfer click
+  $scope.transfer= function() {
+    $state.go('app.view_transfer');
+  };
+
+  // Self cert
+  $scope.self= function() {
+
+    // Choose UID popup
+    $ionicPopup.show({
+      template: '<input type="text" ng-model="walletData.uid">',
+      title: 'Enter a pseudo',
+      subTitle: 'A pseudo is need to let other member find you.',
+      scope: $scope,
+      buttons: [
+        { text: 'Cancel' },
+        {
+          text: '<b>Send</b>',
+          type: 'button-positive',
+          onTap: function(e) {
+            if (!$scope.walletData.uid) {
+              //don't allow the user to close unless he enters a uid
+              e.preventDefault();
+            } else {
+              // TODO : check if not already used
+              return $scope.walletData.uid;
+            }
+          }
+        }
+      ]
+    })
+    .then(function(uid) {
+      UIUtils.loading.show();
+      Wallet.self(uid)
+      .then(function() {
+        UIUtils.loading.hide();
+      })
+      .catch(UIUtils.onError('Could not send self certification'));
+    });
+
+  };
+}
+
+function TransferController($scope, $ionicModal, $state, $ionicHistory, BMA, Wallet, UIUtils) {
+
+  $scope.walletData = {};
+  $scope.formData = {
+    destPub: null,
+    amount: null,
+    comments: null
+  };
+  $scope.dest = null;
+  $scope.udAmount = null;
+
+  WotLookupController.call(this, $scope, BMA, $state);
+
+  $scope.$on('$ionicView.enter', function(e, $state) {
+    if ($state.stateParams != null 
+        && $state.stateParams.pubkey != null
+        && $state.stateParams.pubkey != "undefined") {
+      $scope.destPub = $state.stateParams.pubkey;
+      if ($state.stateParams.uid != null
+        && $state.stateParams.uid != "undefined") {
+        $scope.dest = $state.stateParams.uid;
+      }
+      else {
+        $scope.dest = $scope.destPub; 
+      }
+    }
+
+    // Login and load wallet
+    $scope.loadWallet()
+      .then(function(walletData) {
+        $scope.walletData = walletData;
+        $scope.onUseRelativeChanged();
+      });
+  });
+
+  // When chaing use relative UD
+  $scope.onUseRelativeChanged = function() {
+    if ($scope.walletData.useRelative) {
+      $scope.udAmount = $scope.amount * $scope.walletData.currentUD;
+      $scope.unit = 'universal_dividend';
+      $scope.udUnit = $scope.walletData.currency;
+    } else {
+      $scope.formData.amount = ($scope.formData.amount != "undefined" && $scope.formData.amount != null)
+        ? Math.floor(parseFloat($scope.formData.amount.replace(new RegExp('[,]'), '.')))
+        : null;
+      $scope.udAmount = $scope.amount / $scope.walletData.currentUD;
+      $scope.unit = $scope.walletData.currency;
+      $scope.udUnit = '';
+    }
+  };
+  $scope.$watch('walletData.useRelative', $scope.onUseRelativeChanged, true);
+
+  $ionicModal.fromTemplateUrl('templates/wot/modal_lookup.html', {
+      scope: $scope,
+      focusFirstInput: true
+  }).then(function(modal) {
+    $scope.lookupModal = modal;
+    $scope.lookupModal.hide();
+  });
+
+  $scope.openSearch = function() {
+    $scope.lookupModal.show();
+  }
+
+  $scope.doTransfer = function() {
+    UIUtils.loading.show();
+
+    var amount = $scope.formData.amount;
+    if ($scope.walletData.useRelative 
+      && amount != "undefined" 
+      && amount != null) {
+      amount = $scope.walletData.currentUD 
+               * amount.replace(new RegExp('[.,]'), '.');
+    }
+
+    Wallet.transfer($scope.formData.destPub, amount, $scope.formData.comments)
+    .then(function() {
+      UIUtils.loading.hide();
+      $ionicHistory.goBack()
+    })
+    .catch(UIUtils.onError('Could not send transaction'));
+  };
+
+  $scope.closeLookup = function() {
+    $scope.lookupModal.hide();
+  }
+
+  $scope.doSelectIdentity = function(pub, uid) {
+    if (uid != "undefined" && uid != null) {
+        $scope.dest = uid;
+    }
+    else {
+        $scope.dest = uid;
+    }
+    $scope.formData.destPub = pub;
+    $scope.lookupModal.hide();
+  }
+}
diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js
new file mode 100644
index 0000000000000000000000000000000000000000..6b6c7058d3f1d6ae22d9a02c6b0e9588b2820ef5
--- /dev/null
+++ b/www/js/controllers/wot-controllers.js
@@ -0,0 +1,109 @@
+angular.module('cesium.wot.controllers', ['cesium.services'])
+
+  .config(function($stateProvider, $urlRouterProvider) {
+    $stateProvider
+
+      .state('app.view_identity', {
+        url: "/wot/:pub",
+        views: {
+          'menuContent': {
+            templateUrl: "templates/wot/view_identity.html",
+            controller: 'IdentityCtrl'
+          }
+        }
+      })
+  })
+
+  .controller('IdentityCtrl', IdentityController)
+
+  .controller('WotLookupCtrl', WotLookupController)
+;
+
+function WotLookupController($scope, BMA, $state) {
+
+  $scope.searchChanged = function() {
+    $scope.search.text = $scope.search.text.toLowerCase();
+    if ($scope.search.text.length > 1) {
+      $scope.search.looking = true;
+      return BMA.wot.lookup({ search: $scope.search.text })
+        .then(function(res){
+          $scope.search.looking = false;
+          $scope.search.results = res.results.reduce(function(idties, res) {
+            return idties.concat(res.uids.reduce(function(uids, idty) {
+              return uids.concat({
+                uid: idty.uid,
+                pub: res.pubkey,
+                sigDate: idty.meta.timestamp
+              })
+            }, []));
+          }, []);
+        })
+        .catch(function() {
+          $scope.search.looking = false;
+          $scope.search.results = [];
+        });
+    }
+    else {
+      $scope.search.results = [];
+    }
+  };
+
+  $scope.doSelectIdentity = function(pub, uid) {
+    $state.go('app.view_identity', {pub: pub});
+  };
+}
+
+function IdentityController($scope, $state, BMA, Wallet, UIUtils, $q) {
+
+  $scope.identity = {};
+  $scope.hasSelf = false;
+
+  $scope.$on('$ionicView.enter', function(e, $state) {
+    $scope.loadIdentity($state.stateParams.pub);
+  });
+
+  $scope.loadIdentity = function(pub) {
+    UIUtils.loading.show();
+    BMA.wot.lookup({ search: pub })
+      .then(function(res){
+        $scope.identity = res.results.reduce(function(idties, res) {
+          return idties.concat(res.uids.reduce(function(uids, idty) {
+            return uids.concat({
+              uid: idty.uid,
+              pub: res.pubkey,
+              sigDate: idty.meta.timestamp,
+              sig: idty.self
+            })
+          }, []));
+        }, [])[0];
+        $scope.hasSelf = ($scope.identity.uid && $scope.identity.sigDate && $scope.identity.sig);
+        UIUtils.loading.hide();
+      })
+      .catch(UIUtils.onError('Could not load identity'));
+  };
+
+  $scope.signIdentity = function(identity) {
+    $scope.loadWallet()
+    .then(function(walletData) {
+      UIUtils.loading.show();
+      Wallet.sign($scope.identity.uid,
+                  $scope.identity.pub,
+                  $scope.identity.sigDate,
+                  $scope.identity.sig)
+      .then(function() {
+        UIUtils.loading.hide();
+        UIUtils.alertInfo('Identity successfully signed');
+      })
+      .catch(UIUtils.onError('Could not certify identity'));
+    })
+    .catch(UIUtils.onError('Error while login'));
+  };
+
+  // Transfer click
+  $scope.transfer = function() {
+    $state.go('app.view_transfer_uid', {
+        pubkey: $scope.identity.pubkey,
+        uid: $scope.identity.uid,
+      });
+  };
+}
\ No newline at end of file
diff --git a/www/js/explore-controller.js b/www/js/explore-controller.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/www/js/home-controller.js b/www/js/home-controller.js
deleted file mode 100644
index b9f1ebea9f2bb48a316729001bca1c1ba192f70e..0000000000000000000000000000000000000000
--- a/www/js/home-controller.js
+++ /dev/null
@@ -1,805 +0,0 @@
-
-angular.module('cesium.controllers', ['cesium.services'])
-
-  .config(function($httpProvider) {
-    //Enable cross domain calls
-   $httpProvider.defaults.useXDomain = true;
-
-    //Remove the header used to identify ajax call  that would prevent CORS from working
-    delete $httpProvider.defaults.headers.common['X-Requested-With'];
-  })
-
-  .controller('HomeCtrl', HomeController)
-
-  .controller('CurrenciesCtrl', CurrenciesController)
-
-  .controller('ExploreCtrl', ExploreController)
-
-  .controller('IdentityCtrl', IdentityController)
-
-  .controller('PeerCtrl', PeerController)
-
-  .controller('WalletCtrl', WalletController)
-
-  .controller('TransferCtrl', TransferController)
-
-;
-
-function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate) {
-  // Form data for the login modal
-  $scope.loginData = {
-    username: null,
-    password: null
-  };
-
-  // Login modal
-  $scope.loginModal = "undefined";
-
-  // Create the login modal that we will use later
-  $ionicModal.fromTemplateUrl('templates/login.html', {
-    scope: $scope,
-    focusFirstInput: true
-  }).then(function(modal) {
-    $scope.loginModal = modal;
-    $scope.loginModal.hide();
-  });
-
-  // Open login modal
-  $scope.login = function(callback) {
-    if ($scope.loginModal != "undefined" && $scope.loginModal != null) {
-      $scope.loginModal.show();
-      $scope.loginData.callback = callback;
-    }
-    else{
-      $timeout($scope.login, 2000);
-    }    
-  };
-
-  // Login and load wallet
-  $scope.loadWallet = function() {
-    return $q(function(resolve, reject){
-      if (!Wallet.isLogin()) {
-        $scope.login(function() {
-          Wallet.loadData()
-            .then(function(walletData){
-              resolve(walletData);
-            })
-            .catch(function(err) {
-              console.error('>>>>>>>' , err);
-              UIUtils.alert.error('Your braower is not compatible with cryptographic features.');
-              UIUtils.loading.hide();
-              reject(err);
-            });
-        });
-      }
-      else if (!Wallet.data.loaded) {
-        Wallet.loadData()
-          .then(function(walletData){
-            resolve(walletData);
-          })
-          .catch(function(err) {
-            console.error('>>>>>>>' , err);
-            UIUtils.alert.error('Could not fetch wallet informations from remote uCoin node.');
-            UIUtils.loading.hide();
-            reject(err);
-          });
-      }
-      else {
-        resolve(Wallet.data);
-      }
-    });
-  };
-
-  // Triggered in the login modal to close it
-  $scope.closeLogin = function() {
-    return $scope.loginModal.hide();
-  };
-
-  // Login form submit
-  $scope.doLogin = function() {
-    $scope.closeLogin();
-    UIUtils.loading.show(); 
-
-    // Call wallet login
-    $q.all([
-      Wallet.login($scope.loginData.username, $scope.loginData.password)
-      .catch(function(err) {
-        $scope.loginData = {}; // Reset login data
-        UIUtils.loading.hide();
-        console.error('>>>>>>>' , err);
-        UIUtils.alert.error('Your browser is not compatible with cryptographic libraries.');
-      })
-      .then(function(){
-        UIUtils.loading.hide();
-        var callback = $scope.loginData.callback;
-        $scope.loginData = {}; // Reset login data
-        if (callback != "undefined" && callback != null) {
-          callback();
-        }
-        // Default: redirect to wallet view
-        else {
-          $state.go('app.view_wallet');
-        }
-      })
-    ]);
-  };
-
-  $scope.loginDataChanged = function() {
-    $scope.loginData.computing=false;
-    $scope.loginData.pubkey=null;
-  };
-
-  $scope.showLoginPubkey = function() {
-    $scope.loginData.computing=true;
-    CryptoUtils.connect($scope.loginData.username, $scope.loginData.password).then(
-        function(keypair) {
-            $scope.loginData.pubkey = CryptoUtils.util.encode_base58(keypair.signPk);
-            $scope.loginData.computing=false;
-        }
-    )
-    .catch(function(err) {
-      $scope.loginData.computing=false;
-      UIUtils.loading.hide();
-      console.error('>>>>>>>' , err);
-      UIUtils.alert.error('Your browser is not compatible with cryptographic libraries.');
-    });
-  };
-
-  // Logout
-  $scope.logout = function() {
-    UIUtils.loading.show();
-    Wallet.logout().then(
-        function() {
-          UIUtils.loading.hide();
-          $ionicSideMenuDelegate.toggleLeft();
-          $state.go('app.home');
-        }
-    );
-  };
-
-  // Is connected
-  $scope.isLogged = function() {
-      return Wallet.isLogin();
-  };
-
-  // Is not connected
-  $scope.isNotLogged = function() {
-    return !Wallet.isLogin();
-  };
-}
-
-function CurrenciesController($scope, $state) {
-
-  $scope.selectedCurrency = '';
-  $scope.knownCurrencies = ['meta_brouzouf'];
-
-  // Called to navigate to the main app
-  $scope.selectCurrency = function(currency) {
-    $scope.selectedCurrency = currency;
-    $state.go('app.explore_tabs');
-  };
-}
-
-function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interval, $timeout) {
-
-  var USE_RELATIVE_DEFAULT = true;
-
-  CurrenciesController.call(this, $scope, $state);
-  LookupController.call(this, $scope, BMA, $state);
-  PeersController.call(this, $scope, $rootScope, BMA, UIUtils, $q, $interval, $timeout);
-
-  $scope.accountTypeMember = null;
-  $scope.accounts = [];
-  $scope.search = { text: '', results: {} };
-  $scope.knownCurrencies = ['meta_brouzouf'];
-  $scope.formData = { useRelative: false };
-  $scope.knownBlocks = [];
-  $scope.entered = false;
-
-  $scope.$on('$ionicView.enter', function(e, $state) {
-    if (!$scope.entered) {
-      $scope.entered = true;
-      $scope.startListeningOnSocket();
-    }
-    $timeout(function() {
-      if ((!$scope.search.peers || $scope.search.peers.length == 0) && $scope.search.lookingForPeers){
-        $scope.updateExploreView();
-      }
-    }, 2000);
-  });
-
-  $scope.startListeningOnSocket = function() {
-
-    // Currency OK
-    BMA.websocket.block().on('block', function(block) {
-      var theFPR = fpr(block);
-      if ($scope.knownBlocks.indexOf(theFPR) === -1) {
-        $scope.knownBlocks.push(theFPR);
-        // We wait 2s when a new block is received, just to wait for network propagation
-        var wait = $scope.knownBlocks.length === 1 ? 0 : 2000;
-        $timeout(function() {
-          $scope.updateExploreView();
-        }, wait);
-      }
-    });
-    BMA.websocket.peer().on('peer', function(peer) {
-      console.log(peer);
-    });
-  };
-
-  $scope.$watch('formData.useRelative', function() {
-    if ($scope.formData.useRelative) {
-      $scope.M = $scope.M / $scope.currentUD;
-      $scope.MoverN = $scope.MoverN / $scope.currentUD;
-      $scope.UD = $scope.UD / $scope.currentUD;
-      $scope.unit = 'universal_dividend';
-      $scope.udUnit = $scope.baseUnit;
-    } else {
-      $scope.M = $scope.M * $scope.currentUD;
-      $scope.MoverN = $scope.MoverN * $scope.currentUD;
-      $scope.UD = $scope.UD * $scope.currentUD;
-      $scope.unit = $scope.baseUnit;
-      $scope.udUnit = '';
-    }
-  }, true);
-
-  $scope.doUpdate = function() {
-    $scope.updateExploreView();
-  };
-
-  $scope.updateExploreView = function() {
-
-    UIUtils.loading.show();
-    $scope.formData.useRelative = false;
-
-    $q.all([
-
-      // Get the currency parameters
-      BMA.currency.parameters()
-        .then(function(json){
-          $scope.c = json.c;
-          $scope.baseUnit = json.currency;
-          $scope.unit = json.currency;
-        }),
-
-      // Get the current block informations
-      BMA.blockchain.current()
-        .then(function(block){
-          $scope.M = block.monetaryMass;
-          $scope.N = block.membersCount;
-          $scope.time  = moment(block.medianTime*1000).format('YYYY-MM-DD HH:mm');
-          $scope.difficulty  = block.powMin;
-        }),
-
-      // Get the UD informations
-      BMA.blockchain.stats.ud()
-        .then(function(res){
-          if (res.result.blocks.length) {
-            var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1];
-            return BMA.blockchain.block({ block: lastBlockWithUD })
-              .then(function(block){
-                $scope.currentUD = block.dividend;
-                $scope.UD = block.dividend;
-                $scope.Nprev = block.membersCount;
-              });
-          }
-        })
-    ])
-
-      // Done
-      .then(function(){
-        $scope.M = $scope.M - $scope.UD*$scope.Nprev;
-        $scope.MoverN = $scope.M / $scope.Nprev;
-        $scope.cactual = 100 * $scope.UD / $scope.MoverN;
-        $scope.formData.useRelative = USE_RELATIVE_DEFAULT;
-        UIUtils.loading.hide();
-      })
-      .catch(function(err) {
-        console.error('>>>>>>>' , err);
-        UIUtils.alert.error('Could not fetch informations from remote uCoin node.');
-        UIUtils.loading.hide();
-      })
-      .then(function(){
-        // Network
-        $scope.searchPeers();
-      });
-  };
-}
-
-function LookupController($scope, BMA, $state) {
-
-  $scope.searchChanged = function() {
-    $scope.search.text = $scope.search.text.toLowerCase();
-    if ($scope.search.text.length > 1) {
-      $scope.search.looking = true;
-      return BMA.wot.lookup({ search: $scope.search.text })
-        .then(function(res){
-          $scope.search.looking = false;
-          $scope.search.results = res.results.reduce(function(idties, res) {
-            return idties.concat(res.uids.reduce(function(uids, idty) {
-              return uids.concat({
-                uid: idty.uid,
-                pub: res.pubkey,
-                sigDate: idty.meta.timestamp
-              })
-            }, []));
-          }, []);
-        })
-        .catch(function() {
-          $scope.search.looking = false;
-          $scope.search.results = [];
-        });
-    }
-    else {
-      $scope.search.results = [];
-    }
-  };
-
-  $scope.doSelectIdentity = function(pub, uid) {
-    $state.go('app.view_identity', {pub: pub});
-  };
-
-}
-
-function IdentityController($scope, $state, BMA, Wallet, UIUtils, $q) {
-
-  $scope.$on('$ionicView.enter', function(e, $state) {
-    $scope.showIdentity($state.stateParams.pub);
-  });
-
-  $scope.identity = {};
-
-  $scope.showIdentity = function(pub) {
-
-     BMA.wot.lookup({ search: pub })
-        .then(function(res){
-          $scope.identity = res.results.reduce(function(idties, res) {
-            return idties.concat(res.uids.reduce(function(uids, idty) {
-              return uids.concat({
-                uid: idty.uid,
-                pub: res.pubkey,
-                sigDate: idty.meta.timestamp,                
-                sig: idty.self
-              })
-            }, []));
-          }, [])[0];
-        })
-  };
-
-  $scope.hasSelf = function() {
-    return ($scope.identity.uid
-      && $scope.identity.sigDate
-      && $scope.identity.sig);
-  }
-
-  $scope.signIdentity = function(identity) {
-    $scope.loadWallet()
-    .then(function(walletData) {
-      UIUtils.loading.show();
-      Wallet.sign($scope.identity.uid,
-                  $scope.identity.pub,
-                  $scope.identity.sigDate,
-                  $scope.identity.sig)
-      .then(function() {
-        UIUtils.loading.hide();
-        alert('Identity signed');
-      })
-      .catch(function(err) {        
-        console.error('>>>>>>>' , err);
-        UIUtils.alert.error('Error while signing identity: ' + err);
-        UIUtils.loading.hide();
-      });
-    })
-    .catch(function(err) {      
-      console.error('>>>>>>>' , err);
-      UIUtils.alert.error('Error while signing identity: ' + err);
-    });
-  };
-
-  // Transfer click
-  $scope.transfer = function() {
-    $state.go('app.view_transfer', {
-        pubkey: $scope.identity.pubkey,
-        uid: $scope.identity.uid,
-      });
-  };
-
-   
-}
-
-function PeersController($scope, $rootScope, BMA, UIUtils, $q, $interval, $timeout) {
-
-  var newPeers = [], interval, lookingForPeers;
-  $scope.search.lookingForPeers = false;
-  $scope.search.peers = [];
-
-  $scope.overviewPeers = function() {
-    var currents = {}, block;
-    for (var i = 0, len = $scope.search.peers.length; i < len; i++) {
-      block = $scope.search.peers[i].current;
-      if (block) {
-        var bid = fpr(block);
-        currents[bid] = currents[bid] || 0;
-        currents[bid]++;
-      }
-    }
-    var fprs = _.keys(currents).map(function(key) {
-      return { fpr: key, qty: currents[key] };
-    });
-    var best = _.max(fprs, function(obj) {
-      return obj.qty;
-    });
-    var p;
-    for (var j = 0, len2 = $scope.search.peers.length; j < len2; j++) {
-      p = $scope.search.peers[j];
-      p.hasMainConsensusBlock = fpr(p.current) == best.fpr;
-      p.hasConsensusBlock = !p.hasMainConsensusBlock && currents[fpr(p.current)] > 1;
-    }
-    $scope.search.peers = _.uniq($scope.search.peers, false, function(peer) {
-      return peer.pubkey;
-    });
-    $scope.search.peers = _.sortBy($scope.search.peers, function(p) {
-      var score = 1
-        + 10000 * (p.online ? 1 : 0)
-        + 1000  * (p.hasMainConsensusBlock ? 1 : 0) +
-        + 100   * (p.uid ? 1 : 0);
-      return -score;
-    });
-  };
-
-  $scope.searchPeers = function() {
-
-    if (interval) {
-      $interval.cancel(interval);
-    }
-
-    interval = $interval(function() {
-      if (newPeers.length) {
-        $scope.search.peers = $scope.search.peers.concat(newPeers.splice(0));
-        $scope.overviewPeers();
-      } else if (lookingForPeers && !$scope.search.lookingForPeers) {
-        // The peer lookup endend, we can make a clean final report
-        $timeout(function(){
-          lookingForPeers = false;
-          $scope.overviewPeers();
-        }, 1000);
-      }
-    }, 1000);
-
-    var known = {};
-    $rootScope.members = [];
-    $scope.search.peers = [];
-    $scope.search.lookingForPeers = true;
-    lookingForPeers = true;
-    return BMA.network.peering.peers({ leaves: true })
-      .then(function(res){
-        return BMA.wot.members()
-          .then(function(json){
-            $rootScope.members = json.results;
-            return res;
-          });
-      })
-      .then(function(res){
-        return $q.all(res.leaves.map(function(leaf) {
-          return BMA.network.peering.peers({ leaf: leaf })
-            .then(function(subres){
-              var peer = subres.leaf.value;
-              if (peer) {
-                peer = new Peer(peer);
-                // Test each peer only once
-                if (!known[peer.getURL()]) {
-                  peer.dns = peer.getDns();
-                  peer.blockNumber = peer.block.replace(/-.+$/, '');
-                  var member = _.findWhere($rootScope.members, { pubkey: peer.pubkey });
-                  peer.uid = member && member.uid;
-                  newPeers.push(peer);
-                  var node = BMA.instance(peer.getURL());
-                  return node.blockchain.current()
-                    .then(function(block){
-                      peer.current = block;
-                      peer.online = true;
-                      peer.server = peer.getURL();
-                      if ($scope.knownBlocks.indexOf(fpr(block)) === -1) {
-                        $scope.knownBlocks.push(fpr(block));
-                      }
-                    })
-                    .catch(function(err) {
-                    })
-                }
-              }
-            })
-        }))
-          .then(function(){
-            $scope.search.lookingForPeers = false;
-          })
-      })
-      .catch(function(err) {
-        //console.log(err);
-        //UIUtils.alert.error('Could get peers from remote uCoin node.');
-        //$scope.search.lookingForPeers = false;
-      });
-  };
-
-  $scope.viewPeer = function() {
-
-  };
-}
-
-function fpr(block) {
-  return block && [block.number, block.hash].join('-');
-}
-
-function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA, UIUtils, $q, $timeout, Wallet, CryptoUtils, $ionicSideMenuDelegate) {
-
-  // With the new view caching in Ionic, Controllers are only called
-  // when they are recreated or on app start, instead of every page change.
-  // To listen for when this page is active (for example, to refresh data),
-  // listen for the $ionicView.enter event:
-  //$scope.$on('$ionicView.enter', function(e) {
-  //});
-
-  CurrenciesController.call(this, $scope, $state);
-  LookupController.call(this, $scope, BMA, $state);
-  LoginController.call(this, $scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate);
-
-  $scope.accountTypeMember = null;
-  $scope.accounts = [];
-  $scope.search = { text: '', results: {} };
-  $scope.knownCurrencies = ['meta_brouzouf'];
-
-  // Called to navigate to the main app
-  $scope.cancel = function() {
-    $scope.modal.hide();
-    $timeout(function(){
-      $scope.selectedCurrency = '';
-      $scope.accountTypeMember = null;
-      $scope.search.text = '';
-      $scope.search.results = [];
-    }, 200);
-  };
-
-  $scope.$on('currencySelected', function() {
-    $ionicSlideBoxDelegate.slide(1);
-  });
-
-  $scope.selectAccountTypeMember = function(bool) {
-    $scope.accountTypeMember = bool;
-    $ionicSlideBoxDelegate.slide(2);
-  };
-
-  $scope.next = function() {
-    $ionicSlideBoxDelegate.next();
-  };
-  $scope.previous = function() {
-    $ionicSlideBoxDelegate.previous();
-  };
-
-  // Called each time the slide changes
-  $scope.slideChanged = function(index) {
-    $scope.slideIndex = index;
-    $scope.nextStep = $scope.slideIndex == 2 ? 'Start using MyApp' : 'Next';
-  };
-
-  $scope.addAccount = function() {
-    $scope.modal.show();
-    $scope.slideChanged(0);
-    $ionicSlideBoxDelegate.slide(0);
-    $ionicSlideBoxDelegate.enableSlide(false);
-    // TODO: remove default
-    //$timeout(function() {
-    //  $scope.selectedCurrency = $scope.knownCurrencies[0];
-    //  $scope.accountTypeMember = true;
-    //  $scope.searchChanged();
-    //  $scope.search.text = 'cgeek';
-    //  $ionicSlideBoxDelegate.next();
-    //  $ionicSlideBoxDelegate.next();
-    //}, 300);
-  };
-
-  // Create the account modal that we will use later
-  $ionicModal.fromTemplateUrl('templates/account/new_account.html', {
-    scope: $scope
-  }).then(function(modal) {
-    $scope.modal = modal;
-    $scope.modal.hide();
-    // TODO: remove auto add account when done
-    //$timeout(function() {
-    //  $scope.addAccount();
-    //}, 400);
-  });
-
-  $scope.selectCurrency = function(currency) {
-    $scope.selectedCurrency = currency;
-    $scope.next();
-  }
-}
-
-
-function WalletController($scope, $state, $q, UIUtils, Wallet, $ionicPopup) {
-
-  $scope.walletData = {};
-  $scope.convertedBalance = 0;
-  $scope.hasCredit = false;
-  $scope.isMember = false;
-
-  $scope.$on('$ionicView.enter', function(e, $state) {
-    $scope.loadWallet()
-      .then(function(wallet) {
-        $scope.updateWalletView(wallet);
-      });
-  });
-
-  $scope.refreshConvertedBalance = function() {
-    if ($scope.walletData.useRelative) {
-      $scope.convertedBalance = $scope.walletData.balance / $scope.walletData.currentUD;
-      $scope.unit = 'universal_dividend';
-      $scope.udUnit = $scope.walletData.currency;
-    } else {
-      $scope.convertedBalance = $scope.walletData.balance;
-      $scope.unit = $scope.walletData.currency;
-      $scope.udUnit = '';
-    }
-  };
-  $scope.$watch('walletData.useRelative', $scope.refreshConvertedBalance, true);
-  $scope.$watch('walletData.balance', $scope.refreshConvertedBalance, true);
-
-  // Update view
-  $scope.updateWalletView = function(wallet) {
-    $scope.walletData = wallet;
-    $scope.hasCredit = $scope.walletData.balance != "undefined" && ($scope.walletData.balance > 0);
-    $scope.isMember = (wallet.requirements != null);
-  };
-
-  // Has credit
-  $scope.hasCredit= function() {
-    return $scope.balance > 0;
-  };
-
-  // Transfer click
-  $scope.transfer= function() {
-    $state.go('app.view_transfer');
-  };
-
-  // Self cert
-  $scope.self= function() {
-
-    // ASk uid
-    $ionicPopup.show({
-      template: '<input type="text" ng-model="walletData.uid">',
-      title: 'Enter Pseudo',
-      subTitle: 'Pseudo is used by other member member to find you',
-      scope: $scope,
-      buttons: [
-        { text: 'Cancel' },
-        {
-          text: '<b>Send</b>',
-          type: 'button-positive',
-          onTap: function(e) {
-            if (!$scope.walletData.uid) {
-              //don't allow the user to close unless he enters wifi password
-              e.preventDefault();
-            } else {
-              return $scope.walletData.uid;
-            }
-          }
-        }
-      ]
-    })
-    .then(function(uid) {
-      UIUtils.loading.show();
-      Wallet.self(uid)
-      .then(function() {
-        UIUtils.loading.hide();
-      })
-      .catch(function(err) {
-        console.error('>>>>>>>' , err);
-        UIUtils.alert.error('Error while sending self certification: ' + err);
-        UIUtils.loading.hide();
-      });
-    });
-    
-
-  };
-}
-
-
-function TransferController($scope, $ionicModal, Wallet, UIUtils, $state, $ionicHistory) {
-
-  $scope.walletData = {};
-  $scope.formData = {
-    destPub: null,
-    amount: null,
-    comments: null
-  };
-  $scope.dest = null;
-  $scope.udAmount = null;
-
-  $scope.$on('$ionicView.enter', function(e, $state) {
-    if ($state.stateParams != null 
-        && $state.stateParams.pubkey != null
-        && $state.stateParams.pubkey != "undefined") {
-      $scope.destPub = $state.stateParams.pubkey;
-      if ($state.stateParams.uid != null
-        && $state.stateParams.uid != "undefined") {
-        $scope.dest = $state.stateParams.uid;
-      }
-      else {
-        $scope.dest = $scope.destPub; 
-      }
-    }
-
-    // Login and load wallet
-    $scope.loadWallet()
-      .then(function(walletData) {
-        $scope.walletData = walletData;
-        $scope.onUseRelativeChanged();
-      });
-  });
-
-  // When chaing use relative UD
-  $scope.onUseRelativeChanged = function() {
-    if ($scope.walletData.useRelative) {
-      $scope.udAmount = $scope.amount * $scope.walletData.currentUD;
-      $scope.unit = 'universal_dividend';
-      $scope.udUnit = $scope.walletData.currency;
-    } else {
-      $scope.formData.amount = ($scope.formData.amount != "undefined" && $scope.formData.amount != null)
-        ? Math.floor(parseFloat($scope.formData.amount.replace(new RegExp('[,]'), '.')))
-        : null;
-      $scope.udAmount = $scope.amount / $scope.walletData.currentUD;
-      $scope.unit = $scope.walletData.currency;
-      $scope.udUnit = '';
-    }
-  };
-  $scope.$watch('walletData.useRelative', $scope.onUseRelativeChanged, true);
-
-  $ionicModal.fromTemplateUrl('templates/wot/modal_lookup.html', {
-      scope: $scope,
-      focusFirstInput: true
-  }).then(function(modal) {
-    $scope.lookupModal = modal;
-    $scope.lookupModal.hide();
-  });
-
-  $scope.openSearch = function() {
-    $scope.lookupModal.show();
-  }
-
-  $scope.doTransfer = function() {
-    UIUtils.loading.show();
-
-    var amount = $scope.formData.amount;
-    if ($scope.walletData.useRelative 
-      && amount != "undefined" 
-      && amount != null) {
-      amount = $scope.walletData.currentUD 
-               * amount.replace(new RegExp('[.,]'), '.');
-    }
-
-    Wallet.transfer($scope.formData.destPub, amount, $scope.formData.comments)
-    .then(function() {
-      UIUtils.loading.hide();
-      $ionicHistory.goBack()
-    })
-    .catch(function(err) {
-      console.error('>>>>>>>' , err);
-      UIUtils.alert.error('Could not send transaction: ' + err);
-      UIUtils.loading.hide();
-    });
-  };
-
-  $scope.closeLookup = function() {
-    $scope.lookupModal.hide();
-  }
-
-  $scope.doSelectIdentity = function(pub, uid) {
-    if (uid != "undefined" && uid != null) {
-        $scope.dest = uid;
-    }
-    else {
-        $scope.dest = uid;
-    }
-    $scope.formData.destPub = pub;
-    $scope.lookupModal.hide();
-  }
-}
diff --git a/www/js/services.js b/www/js/services.js
index 4ba0959585279ce5c6bbea4f654582404c4800ef..44821043a3a0394403c3405523ae03c7e11181ed 100644
--- a/www/js/services.js
+++ b/www/js/services.js
@@ -1,849 +1,6 @@
-//var Base58, Base64, scrypt_module_factory = null, nacl_factory = null;
-
-angular.module('cesium.services', ['ngResource'])
-
-.factory('BMA', function($http, $q) {
-
-    function BMA(server, wsServer) {
-        if (wsServer == "undefined" || wsServer == null) {
-            wsServer = server;
-        }
-
-      function processError(reject, data) {
-        if (data != null && data.message != "undefined" && data.message != null) {
-          reject(data.ucode + ": " + data.message);
-        }
-        else {
-          reject('Unknown error from ucoin node');
-        }
-      }
-
-      function prepare(uri, params, config, callback) {
-        var pkeys = [], queryParams = {}, newUri = uri;
-        if (typeof params == 'object') {
-          pkeys = _.keys(params);
-        }
-
-        pkeys.forEach(function(pkey){
-          var prevURI = newUri;
-          newUri = newUri.replace(new RegExp(':' + pkey), params[pkey]);
-          if (prevURI == newUri) {
-            queryParams[pkey] = params[pkey];
-          }
-        });
-        config.params = queryParams;
-        callback(newUri, config);
-      }
-
-      function getResource(uri) {
-        return function(params) {
-          return $q(function(resolve, reject) {
-            var config = {
-              timeout: 4000
-            };
-
-            prepare(uri, params, config, function(uri, config) {
-                $http.get(uri, config)
-                .success(function(data, status, headers, config) {
-                  resolve(data);
-                })
-                .error(function(data, status, headers, config) {
-                  processError(reject, data);
-                });
-            });
-          });
-        }
-      }
-
-      function postResource(uri) {
-        return function(data, params) {
-          return $q(function(resolve, reject) {
-            var config = {
-              timeout: 4000,
-              headers : {'Content-Type' : 'application/json'}
-            };
-
-            prepare(uri, params, config, function(uri, config) {
-                $http.post(uri, data, config)
-                .success(function(data, status, headers, config) {
-                  resolve(data);
-                })
-                .error(function(data, status, headers, config) {
-                  processError(reject, data);
-                });
-            });
-          });
-        }
-      }
-
-      function ws(uri) {
-        var sock = new WebSocket(uri);
-        return {
-          on: function(type, callback) {
-            sock.onmessage = function(e) {
-              callback(JSON.parse(e.data));
-            };
-          }
-        };
-      }
-
-      return {
-        wot: {
-          lookup: getResource('http://' + server + '/wot/lookup/:search'),
-          members: getResource('http://' + server + '/wot/members'),
-          requirements: getResource('http://' + server + '/wot/requirements/:pubkey'),
-          add: postResource('http://' + server + '/wot/add')
-        },
-        network: {
-          peering: {
-            peers: getResource('http://' + server + '/network/peering/peers')
-          },
-          peers: getResource('http://' + server + '/network/peers')
-        },
-        currency: {
-          parameters: getResource('http://' + server + '/blockchain/parameters')
-        },
-        blockchain: {
-          current: getResource('http://' + server + '/blockchain/current'),
-          block: getResource('http://' + server + '/blockchain/block/:block'),
-          stats: {
-            ud: getResource('http://' + server + '/blockchain/with/ud'),
-            tx: getResource('http://' + server + '/blockchain/with/tx')
-          },
-          membership: postResource('http://' + server + '/blockchain/membership'),
-        },
-
-        tx: {
-          sources: getResource('http://' + server + '/tx/sources/:pubkey'),
-          process: postResource('http://' + server + '/tx/process'),
-          history: {
-            all: getResource('http://' + server + '/tx/history/:pubkey'),
-            times: getResource('http://' + server + '/tx/history/:pubkey/times/:from/:to'),
-            blocks: getResource('http://' + server + '/tx/history/:pubkey/blocks/:from/:to')
-          }
-        },
-        websocket: {
-          block: function() {
-            return ws('ws://' + wsServer + '/ws/block');
-          },
-          peer: function() {
-            return ws('ws://' + wsServer + '/ws/peer');
-          }
-        }
-      }
-    }
-    //var service = BMA('metab.ucoin.fr', 'metab.ucoin.fr:9201');
-    //var service = BMA('192.168.0.28:9201');
-    var service = BMA('metab.ucoin.io');
-    service.instance = BMA;
-  return service;
-})
-
-.factory('UIUtils', function($ionicLoading, $ionicPopup) {
-  function alertError(err, subtitle) {
-    var message = err.message || err;
-    return $ionicPopup.show({
-      template: '<p>' + (message || 'Unknown error') + '</p>',
-      title: 'Application error',
-      subTitle: subtitle,
-      buttons: [
-        {
-          text: '<b>OK</b>',
-          type: 'button-assertive'
-        }
-      ]
-    });
-  }
-
-  function hideLoading(){
-    $ionicLoading.hide();
-  }
-
-  function showLoading() {
-    $ionicLoading.show({
-      template: 'Loading...'
-    });
-  }
-
-  function onError(msg) {
-    return function(err) {
-      console.error('>>>>>>>' , err);
-      alertError(msg + ': ' + err);
-      hideLoading();
-    }
-  }
-
-  return {
-    alert: {
-      error: alertError
-    },
-    loading: {
-      show: showLoading,
-      hide: hideLoading
-    },
-    onError: onError
-  };
-})
-
-.factory('CryptoUtils', function($q, $timeout) {
-
-    var async_load_scrypt = function() {
-        if (typeof module !== 'undefined' && module.exports) {
-            // add node.js implementations
-            require('scrypt-em');
-            return scrypt_module_factory();
-        }
-        else if (scrypt_module_factory !== null){
-            return scrypt_module_factory();
-        }
-        else {
-            return $timeout(async_load_scrypt, 100);
-        }
-    },
-
-    async_load_nacl = function() {
-        if (typeof module !== 'undefined' && module.exports) {
-            // add node.js implementations
-            require('nacl_factory');
-            return nacl_factory.instantiate();
-        }
-        else if (nacl_factory !== null){
-            return nacl_factory.instantiate();
-        }
-        else {
-            return $timeout(async_load_nacl, 100);
-        }
-    },
-
-    async_load_base58 = function() {
-        if (typeof module !== 'undefined' && module.exports) {
-            // add node.js implementations
-            require('base58');
-            return Base58;
-        }
-        else if (Base58 !== null){
-            return Base58;
-        }
-        else {
-            return $timeout(async_load_base58, 100);
-        }
-    },
-
-    async_load_base64 = function() {
-        if (typeof module !== 'undefined' && module.exports) {
-            // add node.js implementations
-            require('base58');
-            return Base64;
-        }
-        else if (Base64 !== null){
-            return Base64;
-        }
-        else {
-            return setTimetout(async_load_base64, 100);
-        }
-    };
-
-    function CryptoUtils() {
-      var
-       // Const
-       crypto_sign_BYTES= 64,
-       SEED_LENGTH= 32, // Length of the key
-       SCRYPT_PARAMS= {
-                "N":4096,
-                "r":16,
-                "p":1
-              }
-
-        // load libraries
-        scrypt = async_load_scrypt(),
-        nacl = async_load_nacl(),
-        base58 = async_load_base58(),
-        base64 = async_load_base64(),
-        decode_utf8 = function(s) {
-            var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length);
-            for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
-            return b;
-        },
-        encode_base58 = function(a) {
-            return base58.encode(a);
-        },
-
-       /**
-        * Create a key pair, from salt+password, and  return a wallet object
-        */
-        connect = function(salt, password) {
-              return $q(function(resolve, reject) {
-                  var seed = scrypt.crypto_scrypt(
-                                              nacl.encode_utf8(password),
-                                              nacl.encode_utf8(salt),
-                                              4096, 16, 1, 32 // TODO: put in var SCRYPT_PARAMS
-                                           );
-                   var keypair = nacl.crypto_sign_keypair_from_seed(seed);
-                   resolve(keypair);
-                })
-          },
-
-        /**
-        * Verify a signature of a message, for a pubkey
-        */
-        verify = function (message, signature, pubkey) {
-            return $q(function(resolve, reject) {
-                var msg = decode_utf8(message);
-                var sig = base64.decode(signature);
-                var pub = base58.decode(pubkey);
-                var m = new Uint8Array(crypto_sign_BYTES + msg.length);
-                var sm = new Uint8Array(crypto_sign_BYTES + msg.length);
-                var i;
-                for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i];
-                for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i];
-
-                // Call to verification lib...
-                var verified = nacl.crypto_sign_open(sm, pub) !== null;
-                resolve(verified);
-            });
-        },
-
-        /**
-        * Sign a message, from a wallet
-        */
-        sign = function(message, keypair) {
-          return $q(function(resolve, reject) {
-              var m = decode_utf8(message);
-              var sk = keypair.signSk;
-              var signedMsg = nacl.crypto_sign(m, sk);
-              var sig = new Uint8Array(crypto_sign_BYTES);
-              for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i];
-              var signature = base64.encode(sig);
-              resolve(signature);
-            })
-        }
-
-        ;
-
-      // Service's exposed methods
-      return {
-          /*
-          TODO: uncomment if need to expose
-          nacl: nacl,
-          scrypt: scrypt,
-          base58: base58,
-          base64: base64,*/
-          util: {
-            encode_utf8: nacl.encode_utf8,
-            decode_utf8: decode_utf8,
-            encode_base58: encode_base58
-          },
-          
-
-          connect: connect,
-          sign: sign,
-          verify: verify
-          //,isCompatible: isCompatible
-       }
-    }
-    var service = CryptoUtils();
-    service.instance = CryptoUtils;
-  return service;
-})
-
-.factory('$localstorage', ['$window', 'CryptoUtils', '$q', function($window, CryptoUtils, $q) {
-  return {
-    set: function(key, value) {
-      $window.localStorage[key] = value;
-    },
-    get: function(key, defaultValue) {
-      return $window.localStorage[key] || defaultValue;
-    },
-    setObject: function(key, value) {
-      $window.localStorage[key] = JSON.stringify(value);
-    },
-    getObject: function(key) {
-      return JSON.parse($window.localStorage[key] || '{}');
-    }
-  }
-}])
-
-.factory('Wallet', ['CryptoUtils', 'BMA', '$q', function(CryptoUtils, BMA, $q) {
-  Wallet = function(id) {
-
-    var
-
-    USE_RELATIVE_DEFAULT = true,
-
-    createData = function() {
-      return {
-        uid: null,
-        pubkey: null,
-        keypair: {
-            signSk: null,
-            signPk: null
-        },
-        balance: 0,
-        sources: null,
-        useRelative: USE_RELATIVE_DEFAULT,
-        currency: null,
-        currentUD: null,
-        history: {},
-        loaded: false,
-        requirements: null
-      };
-    },
-
-    data = createData(),
-
-    reduceTx = function(txArray) {
-        var list = [];
-        txArray.forEach(function(tx) {
-            var issuerIndex = -1;
-            var issuer = tx.issuers.reduce(function(issuer, res, index) {
-                issuerIndex = (res == data.pubkey) ? index : issuerIndex;
-                return issuer + ((res != data.pubkey) ? ', ' + res : '');
-            }, ', ').substring(2);
-            var amount =
-                tx.inputs.reduce(function(sum, input) {
-                    var inputArray = input.split(':',5);
-                    return sum - ((inputArray[0] == issuerIndex) ? parseInt(inputArray[4]) : 0);
-                }, 0);
-            amount += tx.outputs.reduce(function(sum, output) {
-                    var outputArray = output.split(':',2);
-                    return sum + ((outputArray[0] == data.pubkey) ? parseInt(outputArray[1]) : 0);
-                }, 0);
-
-            list.push({
-              time: ((tx.time != null && tx.time != "undefined") ? tx.time : 9999999),
-              amount: amount,
-              issuer: issuer,
-              comments: 'comments',
-              isUD: false,
-              hash: tx.hash,
-              block_number: tx.block_number
-            });
-        });
-
-        return list;
-    },
-
-    login = function(salt, password) {
-        return $q(function(resolve, reject) {
-            CryptoUtils.connect(salt, password).then(
-                function(keypair) {
-                    // Copy result to properties
-                    data.pubkey = CryptoUtils.util.encode_base58(keypair.signPk);
-                    data.keypair = keypair;
-                    resolve();
-                }
-            );
-        });
-    },
-
-    logout = function(username, password) {
-        return $q(function(resolve, reject) {
-            data = createData();
-            resolve();
-        });
-    },
-
-    isLogin = function() {
-        return data.pubkey != "undefined"
-            && data.pubkey != null;
-    },
-
-    isSourceEquals = function(arg1, arg2) {
-        return arg1.type == arg2.type
-            && arg1.fingerprint == arg2.fingerprint
-            && arg1.number == arg2.number
-            && arg1.amount == arg2.amount;
-    },
-
-    loadData = function() {
-        if (data.loaded) {
-          return refreshData();
-        }
-
-        return $q(function(resolve, reject){
-          data.loaded = false;
-
-          //console.log('calling loadData');
-          $q.all([
-
-            // Get currency parameters
-            BMA.currency.parameters()
-              .then(function(json){
-                data.currency = json.currency;
-              }),
-
-            // Get the UD informations
-            BMA.blockchain.stats.ud()
-              .then(function(res){
-                if (res.result.blocks.length) {
-                  var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1];
-                  return BMA.blockchain.block({ block: lastBlockWithUD })
-                    .then(function(block){
-                      data.currentUD = block.dividend;
-                    });
-                  }
-              }),
-
-            // Get sources
-            BMA.tx.sources({pubkey: data.pubkey})
-              .then(function(res){
-                data.sources = res.sources; 
-
-                var balance = 0;
-                if (res.sources.length) {
-                  for (var i=0; i<res.sources.length; i++) {
-                    balance += res.sources[i].amount;
-                    res.sources[i].consumed = false;
-                  }
-                }
-                data.balance = balance;
-              }),
-
-            // Get requirements
-            BMA.wot.requirements({pubkey: data.pubkey})
-              .then(function(res){
-                if (res.identities != "undefined" 
-                    && res.identities != null
-                    && res.identities.length == 1) {
-                  data.requirements = res.identities[0];
-                  data.uid = res.identities[0].uid;
-                }
-              })
-              .catch(function(err) {
-                data.requirements = null; 
-              }),
-
-            // Get transactions
-            BMA.tx.history.all({pubkey: data.pubkey})
-              .then(function(res){
-                var list = reduceTx(res.history.sent);
-                list.push(reduceTx(res.history.received));
-                list.push(reduceTx(res.history.sending));
-                list.push(reduceTx(res.history.receiving));
-                list.push(reduceTx(res.history.pending));
-
-                var history = [];
-                list.forEach(function(tx){
-                  history['T:'+ tx.block_number + tx.hash] = tx;
-                });
-                var result = [];
-                _.keys(history).forEach(function(key) {
-                    result.push(history[key]);
-                })
-                data.history = result.sort(function(tx1, tx2) {
-                     return tx2.time - tx1.time;
-                   });
-              })
-          ])
-          .then(function() {
-            data.loaded = true;
-            resolve(data);           
-          })
-          .catch(function(err) {
-            data.loaded = false;
-            reject(err);
-          });
-        });
-    },
-
-    refreshData = function() {
-        return $q(function(resolve, reject){
-          console.log('calling refreshData');
-
-          $q.all([
-
-            // Get the UD informations
-            BMA.blockchain.stats.ud()
-              .then(function(res){
-                if (res.result.blocks.length) {
-                  var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1];
-                  return BMA.blockchain.block({ block: lastBlockWithUD })
-                    .then(function(block){
-                      data.currentUD = block.dividend;
-                    });
-                  }
-              }),
-
-            // Get requirements
-            BMA.wot.requirements({pubkey: data.pubkey})
-              .then(function(res){
-                if (res.identities != "undefined" 
-                    && res.identities != null
-                    && res.identities.length == 1) {
-                  data.requirements = res.identities[0];
-                  data.uid = res.identities[0].uid;
-                }
-                else {
-                  data.requirements = null;
-                }
-              })
-              .catch(function(err) {
-                data.requirements = null; 
-              }),
-
-            // Get sources
-            BMA.tx.sources({pubkey: data.pubkey})
-              .then(function(res){
-
-                var balance = 0;
-                if (res.sources.length) {
-                  for (var i=0; i<res.sources.length; i++) {
-                    res.sources[i].consumed = false;
-                    if (data.sources.length) {
-                      for (var j=0; j<data.sources.length; j++) {
-                        if (isSourceEquals(res.sources[i], data.sources[j])
-                          && data.sources[j].consumed){
-                          res.sources[i].consumed = true;
-                          break;
-                        }
-                      }
-                    }
-                    if (!res.sources[i].consumed){
-                      balance += res.sources[i].amount;
-                    }
-                  }
-                  data.sources = res.sources;
-                }                
-                data.balance = balance;
-              })
-          ])
-          .then(function() {
-            resolve(data);
-          })
-          .catch(function(err) {
-            reject(err);
-          });
-        });
-    },
-
-    /**
-    * Send a new transaction
-    */
-    transfer = function(destPub, amount, comments) {
-        return $q(function(resolve, reject) {
-
-            if (!isLogin()){
-              reject('Wallet required to be login first.'); return;
-            }
-            if (amount == null) {
-              reject('amount must not be null'); return;
-            }
-            amount = Math.round(amount);
-            if (amount <= 0) {
-              reject('amount must be greater than zero'); return;
-            }
-            if (amount > data.balance) {
-              reject('Not enought credit'); return;
-            }
-
-            var tx = "Version: 1\n"
-              + "Type: Transaction\n"
-              + "Currency: " + data.currency + "\n"
-              + "Issuers:\n"
-              + data.pubkey + "\n"
-              + "Inputs:\n";
-            var sourceAmount = 0; 
-            var inputs = [];
-            for (var i = 0; i<data.sources.length; i++) {
-              var input = data.sources[i];
-              if (input.consumed == "undefined" || !input.consumed){
-                // INDEX:SOURCE:NUMBER:FINGERPRINT:AMOUNT
-                tx += "0:"+input.type+":"+ input.number+":"
-                   + input.fingerprint+":"
-                   + input.amount+"\n";
-                sourceAmount += input.amount;
-                inputs.push(input);
-                if (sourceAmount >= amount) {
-                  break;
-                }
-              }
-            }
-
-            if (sourceAmount < amount) {
-              reject('Not enought sources (max amount: '
-                +(data.useRelative ? (sourceAmount / data.currentUD)+' UD' : sourceAmount)
-                +'). Please wait next block computation.'); 
-              return;
-            }
-
-            tx += "Outputs:\n"
-               // ISSUERS:AMOUNT
-               + destPub +":" + amount + "\n"; 
-            if (sourceAmount > amount) {
-              tx += data.pubkey+":"+(sourceAmount-amount)+"\n";
-            }
-
-            tx += "Comment: "+ (comments!=null?comments:"") + "\n";
-
-
-
-            CryptoUtils.sign(tx, data.keypair)
-              .then(function(signature) {
-                var signedTx = tx + signature + "\n";
-                BMA.tx.process({transaction: signedTx})
-                  .then(function(result) {
-                    data.balance -= amount;
-                    for(var i=0;i<inputs.length;i++)inputs[i].consumed=true;
-                    resolve(result);
-                  })
-                  .catch(function(err){
-                    reject(err);
-                  });
-              })
-              .catch(function(err){
-                reject(err);
-              });
-        });
-    }
-
-    /**
-    * Send self certification
-    */
-    self = function(uid) {
-      return $q(function(resolve, reject) {
-        
-        BMA.blockchain.current()
-        .then(function(block) {
-          // Create the self part to sign
-          var self = 'UID:' + uid + '\n'
-                   + 'META:TS:' + (block.time+1) + '\n';
-
-          CryptoUtils.sign(self, data.keypair)
-          .then(function(signature) {
-            var signedSelf = self + signature + '\n';
-            // Send self
-            BMA.wot.add({pubkey: data.pubkey, self: signedSelf, other: ''})
-            .then(function(result) {
-              // Check requirements
-              BMA.wot.requirements({pubkey: data.pubkey})
-              .then(function(res){
-                if (res.identities != "undefined" 
-                    && res.identities != null
-                    && res.identities.length == 1) {
-                  data.requirements = res.identities[0];
-                  data.uid = uid;
-                  resolve();
-                }
-                else{
-                  reject(); 
-                }
-              })
-              .catch(function(err) {
-                reject();
-              })
-            })
-            .catch(function(err){
-              reject(err);
-            });
-          })
-          .catch(function(err){
-            reject(err);
-          });
-        })
-        .catch(function(err) {
-          reject(err);
-        });
-      });
-    },
-
-    /**
-    * Send identity certification
-    */
-    sign = function(uid, pubkey, timestamp, signature) {
-      return $q(function(resolve, reject) {
-        
-        BMA.blockchain.current()
-        .then(function(block) {
-          // Create the self part to sign
-          var self = 'UID:' + uid + '\n'
-                   + 'META:TS:' + timestamp + '\n'
-                   + signature /*+"\n"*/;
-
-          var cert = self + '\n'
-                + 'META:TS:' + block.number + '-' + block.hash + '\n';
-
-          CryptoUtils.sign(cert, data.keypair)
-          .then(function(signature) {
-            var inlineCert = data.pubkey 
-              + ':' + pubkey 
-              + ':' + block.number
-              + ':' + signature + '\n';
-            BMA.wot.add({pubkey: pubkey, self: self, other: inlineCert})
-              .then(function(result) {
-                resolve(result);
-              })
-              .catch(function(err){
-                reject(err);
-              });
-          })
-          .catch(function(err){
-            reject(err);
-          });
-        })
-        .catch(function(err) {
-          reject(err);
-        });
-      });
-    },
-
-    /**
-    * Serialize to JSON string
-    */
-    toJson = function() {
-      return $q(function(resolve, reject) {
-          var json = JSON.stringify(data);
-          resolve(json);
-        })
-    },
-
-    /**
-    * De-serialize from JSON string
-    */
-    fromJson = function(json) {
-      return $q(function(resolve, reject) {
-          var obj = JSON.parse(json || '{}');
-          if (obj.keypair != "undefined"
-              && obj.keypair != null) {
-              var keypair = obj.keypair;
-
-              // Convert to Uint8Array type
-              var signPk = new Uint8Array(32);
-              for (var i = 0; i < 32; i++) signPk[i] = keypair.signPk[i];
-              keypair.signPk = signPk;
-
-              var signSk = new Uint8Array(64);
-              for (var i = 0; i < 64; i++) signSk[i] = keypair.signSk[i];
-              keypair.signSk = signSk;
-
-              data.pubkey = obj.pubkey;
-              data.keypair = keypair;
-
-              resolve();
-          }
-          else {
-            reject('Not a valid Wallet.data object');
-          }
-        })
-    };
-
-    return {
-        id: id,
-        data: data,
-
-        login: login,
-        logout: logout,
-        isLogin: isLogin,
-        toJson: toJson,
-        fromJson: fromJson,
-        loadData: loadData,
-        refreshData: refreshData,
-        transfer: transfer,
-        self: self,
-        sign: sign
-    }
-  }
-  var service = Wallet('default');
-  service.instance = service;
-  return service;
-}])
+angular.module('cesium.services', [
+    'cesium.bma.services',
+    'cesium.crypto.services',
+    'cesium.utils.services',
+    'cesium.wallet.services'])
 ;
diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js
new file mode 100644
index 0000000000000000000000000000000000000000..75d5fdb2f07e39169833626af1844b51d182da62
--- /dev/null
+++ b/www/js/services/bma-services.js
@@ -0,0 +1,141 @@
+//var Base58, Base64, scrypt_module_factory = null, nacl_factory = null;
+
+angular.module('cesium.bma.services', ['ngResource'])
+
+.factory('BMA', function($http, $q) {
+
+    function BMA(server, wsServer) {
+        if (wsServer == "undefined" || wsServer == null) {
+            wsServer = server;
+        }
+
+      function processError(reject, data) {
+        if (data != null && data.message != "undefined" && data.message != null) {
+          reject(data.ucode + ": " + data.message);
+        }
+        else {
+          reject('Unknown error from ucoin node');
+        }
+      }
+
+      function prepare(uri, params, config, callback) {
+        var pkeys = [], queryParams = {}, newUri = uri;
+        if (typeof params == 'object') {
+          pkeys = _.keys(params);
+        }
+
+        pkeys.forEach(function(pkey){
+          var prevURI = newUri;
+          newUri = newUri.replace(new RegExp(':' + pkey), params[pkey]);
+          if (prevURI == newUri) {
+            queryParams[pkey] = params[pkey];
+          }
+        });
+        config.params = queryParams;
+        callback(newUri, config);
+      }
+
+      function getResource(uri) {
+        return function(params) {
+          return $q(function(resolve, reject) {
+            var config = {
+              timeout: 4000
+            };
+
+            prepare(uri, params, config, function(uri, config) {
+                $http.get(uri, config)
+                .success(function(data, status, headers, config) {
+                  resolve(data);
+                })
+                .error(function(data, status, headers, config) {
+                  processError(reject, data);
+                });
+            });
+          });
+        }
+      }
+
+      function postResource(uri) {
+        return function(data, params) {
+          return $q(function(resolve, reject) {
+            var config = {
+              timeout: 4000,
+              headers : {'Content-Type' : 'application/json'}
+            };
+
+            prepare(uri, params, config, function(uri, config) {
+                $http.post(uri, data, config)
+                .success(function(data, status, headers, config) {
+                  resolve(data);
+                })
+                .error(function(data, status, headers, config) {
+                  processError(reject, data);
+                });
+            });
+          });
+        }
+      }
+
+      function ws(uri) {
+        var sock = new WebSocket(uri);
+        return {
+          on: function(type, callback) {
+            sock.onmessage = function(e) {
+              callback(JSON.parse(e.data));
+            };
+          }
+        };
+      }
+
+      return {
+        wot: {
+          lookup: getResource('http://' + server + '/wot/lookup/:search'),
+          members: getResource('http://' + server + '/wot/members'),
+          requirements: getResource('http://' + server + '/wot/requirements/:pubkey'),
+          add: postResource('http://' + server + '/wot/add')
+        },
+        network: {
+          peering: {
+            peers: getResource('http://' + server + '/network/peering/peers')
+          },
+          peers: getResource('http://' + server + '/network/peers')
+        },
+        currency: {
+          parameters: getResource('http://' + server + '/blockchain/parameters')
+        },
+        blockchain: {
+          current: getResource('http://' + server + '/blockchain/current'),
+          block: getResource('http://' + server + '/blockchain/block/:block'),
+          membership: postResource('http://' + server + '/blockchain/membership'),
+          stats: {
+            ud: getResource('http://' + server + '/blockchain/with/ud'),
+            tx: getResource('http://' + server + '/blockchain/with/tx')
+          }
+        },
+
+        tx: {
+          sources: getResource('http://' + server + '/tx/sources/:pubkey'),
+          process: postResource('http://' + server + '/tx/process'),
+          history: {
+            all: getResource('http://' + server + '/tx/history/:pubkey'),
+            times: getResource('http://' + server + '/tx/history/:pubkey/times/:from/:to'),
+            blocks: getResource('http://' + server + '/tx/history/:pubkey/blocks/:from/:to')
+          }
+        },
+        websocket: {
+          block: function() {
+            return ws('ws://' + wsServer + '/ws/block');
+          },
+          peer: function() {
+            return ws('ws://' + wsServer + '/ws/peer');
+          }
+        }
+      }
+    }
+    //var service = BMA('metab.ucoin.fr', 'metab.ucoin.fr:9201');
+    //var service = BMA('192.168.0.28:9201');
+    var service = BMA('metab.ucoin.io');
+    service.instance = BMA;
+  return service;
+})
+;
diff --git a/www/js/services/crypto-services.js b/www/js/services/crypto-services.js
new file mode 100644
index 0000000000000000000000000000000000000000..77d5b07da3776626cd1c06e4feafdac3e4a3ab95
--- /dev/null
+++ b/www/js/services/crypto-services.js
@@ -0,0 +1,165 @@
+//var Base58, Base64, scrypt_module_factory = null, nacl_factory = null;
+
+angular.module('cesium.crypto.services', ['ngResource'])
+
+.factory('CryptoUtils', function($q, $timeout) {
+
+    var async_load_scrypt = function() {
+        if (typeof module !== 'undefined' && module.exports) {
+            // add node.js implementations
+            require('scrypt-em');
+            return scrypt_module_factory();
+        }
+        else if (scrypt_module_factory !== null){
+            return scrypt_module_factory();
+        }
+        else {
+            return $timeout(async_load_scrypt, 100);
+        }
+    },
+
+    async_load_nacl = function() {
+        if (typeof module !== 'undefined' && module.exports) {
+            // add node.js implementations
+            require('nacl_factory');
+            return nacl_factory.instantiate();
+        }
+        else if (nacl_factory !== null){
+            return nacl_factory.instantiate();
+        }
+        else {
+            return $timeout(async_load_nacl, 100);
+        }
+    },
+
+    async_load_base58 = function() {
+        if (typeof module !== 'undefined' && module.exports) {
+            // add node.js implementations
+            require('base58');
+            return Base58;
+        }
+        else if (Base58 !== null){
+            return Base58;
+        }
+        else {
+            return $timeout(async_load_base58, 100);
+        }
+    },
+
+    async_load_base64 = function() {
+        if (typeof module !== 'undefined' && module.exports) {
+            // add node.js implementations
+            require('base58');
+            return Base64;
+        }
+        else if (Base64 !== null){
+            return Base64;
+        }
+        else {
+            return setTimetout(async_load_base64, 100);
+        }
+    };
+
+    function CryptoUtils() {
+      var
+       // Const
+       crypto_sign_BYTES= 64,
+       SEED_LENGTH= 32, // Length of the key
+       SCRYPT_PARAMS= {
+                "N":4096,
+                "r":16,
+                "p":1
+              }
+
+        // load libraries
+        scrypt = async_load_scrypt(),
+        nacl = async_load_nacl(),
+        base58 = async_load_base58(),
+        base64 = async_load_base64(),
+        decode_utf8 = function(s) {
+            var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length);
+            for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
+            return b;
+        },
+        encode_base58 = function(a) {
+            return base58.encode(a);
+        },
+
+       /**
+        * Create a key pair, from salt+password, and  return a wallet object
+        */
+        connect = function(salt, password) {
+              return $q(function(resolve, reject) {
+                  var seed = scrypt.crypto_scrypt(
+                                              nacl.encode_utf8(password),
+                                              nacl.encode_utf8(salt),
+                                              4096, 16, 1, 32 // TODO: put in var SCRYPT_PARAMS
+                                           );
+                   var keypair = nacl.crypto_sign_keypair_from_seed(seed);
+                   resolve(keypair);
+                })
+          },
+
+        /**
+        * Verify a signature of a message, for a pubkey
+        */
+        verify = function (message, signature, pubkey) {
+            return $q(function(resolve, reject) {
+                var msg = decode_utf8(message);
+                var sig = base64.decode(signature);
+                var pub = base58.decode(pubkey);
+                var m = new Uint8Array(crypto_sign_BYTES + msg.length);
+                var sm = new Uint8Array(crypto_sign_BYTES + msg.length);
+                var i;
+                for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i];
+                for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i];
+
+                // Call to verification lib...
+                var verified = nacl.crypto_sign_open(sm, pub) !== null;
+                resolve(verified);
+            });
+        },
+
+        /**
+        * Sign a message, from a wallet
+        */
+        sign = function(message, keypair) {
+          return $q(function(resolve, reject) {
+              var m = decode_utf8(message);
+              var sk = keypair.signSk;
+              var signedMsg = nacl.crypto_sign(m, sk);
+              var sig = new Uint8Array(crypto_sign_BYTES);
+              for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i];
+              var signature = base64.encode(sig);
+              resolve(signature);
+            })
+        }
+
+        ;
+
+      // Service's exposed methods
+      return {
+          /*
+          TODO: uncomment if need to expose
+          nacl: nacl,
+          scrypt: scrypt,
+          base58: base58,
+          base64: base64,*/
+          util: {
+            encode_utf8: nacl.encode_utf8,
+            decode_utf8: decode_utf8,
+            encode_base58: encode_base58
+          },
+          
+
+          connect: connect,
+          sign: sign,
+          verify: verify
+          //,isCompatible: isCompatible
+       }
+    }
+    var service = CryptoUtils();
+    service.instance = CryptoUtils;
+  return service;
+})
+;
diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js
new file mode 100644
index 0000000000000000000000000000000000000000..41ce70c4d37e8916198795cca61217d9ad44928a
--- /dev/null
+++ b/www/js/services/utils-services.js
@@ -0,0 +1,83 @@
+//var Base58, Base64, scrypt_module_factory = null, nacl_factory = null;
+
+angular.module('cesium.utils.services', ['ngResource'])
+
+.factory('UIUtils', function($ionicLoading, $ionicPopup) {
+  function alertError(err, subtitle) {
+    var message = err.message || err;
+    return $ionicPopup.show({
+      template: '<p>' + (message || 'Unknown error') + '</p>',
+      title: 'Application error',
+      subTitle: subtitle,
+      buttons: [
+        {
+          text: '<b>OK</b>',
+          type: 'button-assertive'
+        }
+      ]
+    });
+  }
+
+  function alertInfo(message, subtitle) {
+      var message = err.message || err;
+      return $ionicPopup.show({
+        template: '<p>' + message + '</p>',
+        title: 'Information',
+        subTitle: subtitle,
+        buttons: [
+          {
+            text: '<b>OK</b>',
+            type: 'button-positive'
+          }
+        ]
+      });
+    }
+
+  function hideLoading(){
+    $ionicLoading.hide();
+  }
+
+  function showLoading() {
+    $ionicLoading.show({
+      template: 'Loading...'
+    });
+  }
+
+  function onError(msg) {
+    return function(err) {
+      console.error('>>>>>>>' , err);
+      alertError(msg + ': ' + err);
+      hideLoading();
+    }
+  }
+
+  return {
+    alert: {
+      error: alertError
+    },
+    loading: {
+      show: showLoading,
+      hide: hideLoading
+    },
+    onError: onError
+  };
+})
+
+.factory('$localstorage', ['$window', 'CryptoUtils', '$q', function($window, CryptoUtils, $q) {
+  return {
+    set: function(key, value) {
+      $window.localStorage[key] = value;
+    },
+    get: function(key, defaultValue) {
+      return $window.localStorage[key] || defaultValue;
+    },
+    setObject: function(key, value) {
+      $window.localStorage[key] = JSON.stringify(value);
+    },
+    getObject: function(key) {
+      return JSON.parse($window.localStorage[key] || '{}');
+    }
+  }
+}])
+
+;
diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js
new file mode 100644
index 0000000000000000000000000000000000000000..248bddefb87933a89d1e1b7c3026227e3916b7d5
--- /dev/null
+++ b/www/js/services/wallet-services.js
@@ -0,0 +1,487 @@
+//var Base58, Base64, scrypt_module_factory = null, nacl_factory = null;
+
+angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', 'cesium.crypto.services'])
+
+.factory('Wallet', ['CryptoUtils', 'BMA', '$q', function(CryptoUtils, BMA, $q) {
+
+  Wallet = function(id) {
+
+    var
+
+    USE_RELATIVE_DEFAULT = true,
+
+    createData = function() {
+      return {
+        pubkey: null,
+        keypair: {
+            signSk: null,
+            signPk: null
+        },
+        balance: 0,
+        sources: null,
+        useRelative: USE_RELATIVE_DEFAULT,
+        currency: null,
+        currentUD: null,
+        history: {},
+        requirements: null,
+        loaded: false
+      };
+    },
+
+    data = createData(),
+
+    reduceTx = function(txArray) {
+        var list = [];
+        txArray.forEach(function(tx) {
+            var issuerIndex = -1;
+            var issuer = tx.issuers.reduce(function(issuer, res, index) {
+                issuerIndex = (res == data.pubkey) ? index : issuerIndex;
+                return issuer + ((res != data.pubkey) ? ', ' + res : '');
+            }, ', ').substring(2);
+            var amount =
+                tx.inputs.reduce(function(sum, input) {
+                    var inputArray = input.split(':',5);
+                    return sum - ((inputArray[0] == issuerIndex) ? parseInt(inputArray[4]) : 0);
+                }, 0);
+            amount += tx.outputs.reduce(function(sum, output) {
+                    var outputArray = output.split(':',2);
+                    return sum + ((outputArray[0] == data.pubkey) ? parseInt(outputArray[1]) : 0);
+                }, 0);
+
+            list.push({
+              time: ((tx.time != null && tx.time != "undefined") ? tx.time : 9999999),
+              amount: amount,
+              issuer: issuer,
+              comments: 'comments',
+              isUD: false,
+              hash: tx.hash,
+              block_number: tx.block_number
+            });
+        });
+
+        return list;
+    },
+
+    login = function(salt, password) {
+        return $q(function(resolve, reject) {
+            CryptoUtils.connect(salt, password).then(
+                function(keypair) {
+                    // Copy result to properties
+                    data.pubkey = CryptoUtils.util.encode_base58(keypair.signPk);
+                    data.keypair = keypair;
+                    resolve();
+                }
+            );
+        });
+    },
+
+    logout = function(username, password) {
+        return $q(function(resolve, reject) {
+            data = createData();
+            resolve();
+        });
+    },
+
+    isLogin = function() {
+        return data.pubkey != "undefined"
+            && data.pubkey != null;
+    },
+
+    isSourceEquals = function(arg1, arg2) {
+        return arg1.type == arg2.type
+            && arg1.fingerprint == arg2.fingerprint
+            && arg1.number == arg2.number
+            && arg1.amount == arg2.amount;
+    },
+
+    loadData = function() {
+        if (data.loaded) {
+          return refreshData();
+        }
+
+        return $q(function(resolve, reject){
+          data.loaded = false;
+
+          $q.all([
+
+            // Get currency parameters
+            BMA.currency.parameters()
+              .then(function(json){
+                data.currency = json.currency;
+              }),
+
+            // Get the UD informations
+            BMA.blockchain.stats.ud()
+              .then(function(res){
+                if (res.result.blocks.length) {
+                  var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1];
+                  return BMA.blockchain.block({ block: lastBlockWithUD })
+                    .then(function(block){
+                      data.currentUD = block.dividend;
+                    });
+                  }
+              }),
+
+            // Get sources
+            BMA.tx.sources({pubkey: data.pubkey})
+              .then(function(res){
+                data.sources = res.sources; 
+
+                var balance = 0;
+                if (res.sources.length) {
+                  for (var i=0; i<res.sources.length; i++) {
+                    balance += res.sources[i].amount;
+                    res.sources[i].consumed = false;
+                  }
+                }
+                data.balance = balance;
+              }),
+
+            // Get requirements
+            BMA.wot.requirements({pubkey: data.pubkey})
+              .then(function(res){
+                if (res.identities != "undefined"
+                    && res.identities != null
+                    && res.identities.length == 1) {
+                  data.requirements = res.identities[0];
+                  data.uid = res.identities[0].uid;
+                }
+              })
+              .catch(function(err) {
+                data.requirements = null;
+              }),
+
+            // Get transactions
+            BMA.tx.history.all({pubkey: data.pubkey})
+              .then(function(res){
+                var list = reduceTx(res.history.sent);
+                list.push(reduceTx(res.history.received));
+                list.push(reduceTx(res.history.sending));
+                list.push(reduceTx(res.history.receiving));
+                list.push(reduceTx(res.history.pending));
+
+                var history = [];
+                list.forEach(function(tx){
+                  history['T:'+ tx.block_number + tx.hash] = tx;
+                });
+                var result = [];
+                _.keys(history).forEach(function(key) {
+                    result.push(history[key]);
+                })
+                data.history = result.sort(function(tx1, tx2) {
+                     return tx2.time - tx1.time;
+                   });
+              })
+          ])
+          .then(function() {
+            data.loaded = true;
+            resolve(data);            
+          })
+          .catch(function(err) {
+            data.loaded = false;
+            reject(err);
+          });
+        });
+    },
+
+    refreshData = function() {
+        return $q(function(resolve, reject){
+          $q.all([
+
+            // Get the UD informations
+            BMA.blockchain.stats.ud()
+              .then(function(res){
+                if (res.result.blocks.length) {
+                  var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1];
+                  return BMA.blockchain.block({ block: lastBlockWithUD })
+                    .then(function(block){
+                      data.currentUD = block.dividend;
+                    });
+                  }
+              }),
+
+            // Get requirements
+            BMA.wot.requirements({pubkey: data.pubkey})
+              .then(function(res){
+                if (res.identities != "undefined"
+                    && res.identities != null
+                    && res.identities.length == 1) {
+                  data.requirements = res.identities[0];
+                  data.uid = res.identities[0].uid;
+                }
+                else {
+                  data.requirements = null;
+                }
+              })
+              .catch(function(err) {
+                data.requirements = null;
+              }),
+
+            // Get sources
+            BMA.tx.sources({pubkey: data.pubkey})
+              .then(function(res){
+
+                var balance = 0;
+                if (res.sources.length) {
+                  for (var i=0; i<res.sources.length; i++) {
+                    res.sources[i].consumed = false;
+                    if (data.sources.length) {
+                      for (var j=0; j<data.sources.length; j++) {
+                        if (isSourceEquals(res.sources[i], data.sources[j])
+                          && data.sources[j].consumed){
+                          res.sources[i].consumed = true;
+                          break;
+                        }
+                      }
+                    }
+                    if (!res.sources[i].consumed){
+                      balance += res.sources[i].amount;
+                    }
+                  }
+                  data.sources = res.sources;
+                }                
+                data.balance = balance;
+              })
+          ])
+          .then(function() {
+            resolve(data);
+          })
+          .catch(function(err) {
+            reject(err);
+          });
+        });
+    },
+
+    /**
+    * Send a new transaction
+    */
+    transfer = function(destPub, amount, comments) {
+        return $q(function(resolve, reject) {
+
+            if (!isLogin()){
+              reject('Wallet required to be login first.'); return;
+            }
+            if (amount == null) {
+              reject('amount must not be null'); return;
+            }
+            amount = Math.round(amount);
+            if (amount <= 0) {
+              reject('amount must be greater than zero'); return;
+            }
+            if (amount > data.balance) {
+              reject('Not enought credit'); return;
+            }
+
+            var tx = "Version: 1\n"
+              + "Type: Transaction\n"
+              + "Currency: " + data.currency + "\n"
+              + "Issuers:\n"
+              + data.pubkey + "\n"
+              + "Inputs:\n";
+            var sourceAmount = 0; 
+            var inputs = [];
+            for (var i = 0; i<data.sources.length; i++) {
+              var input = data.sources[i];
+              if (input.consumed == "undefined" || !input.consumed){
+                // INDEX:SOURCE:NUMBER:FINGERPRINT:AMOUNT
+                tx += "0:"+input.type+":"+ input.number+":"
+                   + input.fingerprint+":"
+                   + input.amount+"\n";
+                sourceAmount += input.amount;
+                inputs.push(input);
+                if (sourceAmount >= amount) {
+                  break;
+                }
+              }
+            }
+
+            if (sourceAmount < amount) {
+              reject('Not enought sources (max amount: '
+                +(data.useRelative ? (sourceAmount / data.currentUD)+' UD' : sourceAmount)
+                +'). Please wait next block computation.'); 
+              return;
+            }
+
+            tx += "Outputs:\n"
+               // ISSUERS:AMOUNT
+               + destPub +":" + amount + "\n"; 
+            if (sourceAmount > amount) {
+              tx += data.pubkey+":"+(sourceAmount-amount)+"\n";
+            }
+
+            tx += "Comment: "+ (comments!=null?comments:"") + "\n";
+
+
+
+            CryptoUtils.sign(tx, data.keypair)
+              .then(function(signature) {
+                var signedTx = tx + signature + "\n";
+                BMA.tx.process({transaction: signedTx})
+                  .then(function(result) {
+                    data.balance -= amount;
+                    for(var i=0;i<inputs.length;i++)inputs[i].consumed=true;
+                    resolve(result);
+                  })
+                  .catch(function(err){
+                    reject(err);
+                  });
+              })
+              .catch(function(err){
+                reject(err);
+              });
+        });
+    },
+
+    /**
+    * Send self certification
+    */
+    self = function(uid) {
+      return $q(function(resolve, reject) {
+
+        BMA.blockchain.current()
+        .then(function(block) {
+          // Create the self part to sign
+          var self = 'UID:' + uid + '\n'
+                   + 'META:TS:' + (block.time+1) + '\n';
+
+          CryptoUtils.sign(self, data.keypair)
+          .then(function(signature) {
+            var signedSelf = self + signature + '\n';
+            // Send self
+            BMA.wot.add({pubkey: data.pubkey, self: signedSelf, other: ''})
+            .then(function(result) {
+              // Check requirements
+              BMA.wot.requirements({pubkey: data.pubkey})
+              .then(function(res){
+                if (res.identities != "undefined"
+                    && res.identities != null
+                    && res.identities.length == 1) {
+                  data.requirements = res.identities[0];
+                  data.uid = uid;
+                  resolve();
+                }
+                else{
+                  reject();
+                }
+              })
+              .catch(function(err) {
+                reject();
+              })
+            })
+            .catch(function(err){
+              reject(err);
+            });
+          })
+          .catch(function(err){
+            reject(err);
+          });
+        })
+        .catch(function(err) {
+          reject(err);
+        });
+      });
+    },
+
+    /**
+    * Send identity certification
+    */
+    sign = function(uid, pubkey, timestamp, signature) {
+      return $q(function(resolve, reject) {
+
+        BMA.blockchain.current()
+        .then(function(block) {
+          // Create the self part to sign
+          var self = 'UID:' + uid + '\n'
+                   + 'META:TS:' + timestamp + '\n'
+                   + signature /*+"\n"*/;
+
+          var cert = self + '\n'
+                + 'META:TS:' + block.number + '-' + block.hash + '\n';
+
+          CryptoUtils.sign(cert, data.keypair)
+          .then(function(signature) {
+            var inlineCert = data.pubkey
+              + ':' + pubkey
+              + ':' + block.number
+              + ':' + signature + '\n';
+            BMA.wot.add({pubkey: pubkey, self: self, other: inlineCert})
+              .then(function(result) {
+                resolve(result);
+              })
+              .catch(function(err){
+                reject(err);
+              });
+          })
+          .catch(function(err){
+            reject(err);
+          });
+        })
+        .catch(function(err) {
+          reject(err);
+        });
+      });
+    },
+
+    /**
+    * Serialize to JSON string
+    */
+    toJson = function() {
+      return $q(function(resolve, reject) {
+          var json = JSON.stringify(data);
+          resolve(json);
+        })
+    },
+
+    /**
+    * De-serialize from JSON string
+    */
+    fromJson = function(json) {
+      return $q(function(resolve, reject) {
+          var obj = JSON.parse(json || '{}');
+          if (obj.keypair != "undefined"
+              && obj.keypair != null) {
+              var keypair = obj.keypair;
+
+              // Convert to Uint8Array type
+              var signPk = new Uint8Array(32);
+              for (var i = 0; i < 32; i++) signPk[i] = keypair.signPk[i];
+              keypair.signPk = signPk;
+
+              var signSk = new Uint8Array(64);
+              for (var i = 0; i < 64; i++) signSk[i] = keypair.signSk[i];
+              keypair.signSk = signSk;
+
+              data.pubkey = obj.pubkey;
+              data.keypair = keypair;
+
+              resolve();
+          }
+          else {
+            reject('Not a valid Wallet.data object');
+          }
+        })
+    };
+
+    return {
+        id: id,
+        data: data,
+        // auth
+        login: login,
+        logout: logout,
+        isLogin: isLogin,
+        loadData: loadData,
+        refreshData: refreshData,
+        // operations
+        transfer: transfer,
+        self: self,
+        sign: sign,
+        // serialization
+        toJson: toJson,
+        fromJson: fromJson
+    }
+  }
+  var service = Wallet('default');
+  service.instance = service;
+  return service;
+}])
+;
diff --git a/www/templates/account/view_wallet.html b/www/templates/account/view_wallet.html
index ee491dd0183f1cc5ddb5e72cf3f24b1102e8fb8e..3b82e5ebbd8095e958f4a35f826de6dbe6364427 100644
--- a/www/templates/account/view_wallet.html
+++ b/www/templates/account/view_wallet.html
@@ -5,13 +5,13 @@
                 
                 <span class="item item-icon-left" ng-if="isMember">
                     <i class="icon ion-person"></i>
-                    User
-                    <span class="badge">{{walletData.uid}}</span>
+                    <h2>{{walletData.uid}}</h2>
+                    <p>Public key: {{walletData.pubkey | formatPubkey}}</p>
                 </span>
 
                 <span class="item item-icon-left" ng-if="!isMember">
                     <i class="icon ion-key"></i>
-                    Pubkey
+                    Public key
                     <span class="badge">{{walletData.pubkey | formatPubkey}}</span>
                 </span>
 
diff --git a/www/templates/wot/view_identity.html b/www/templates/wot/view_identity.html
index bc61831df776c8cf68dd41c589196e216bb73e75..d8cf130e76429858b168d130ccf6ceb5f8fbdef7 100644
--- a/www/templates/wot/view_identity.html
+++ b/www/templates/wot/view_identity.html
@@ -1,17 +1,12 @@
-<ion-view view-title="Identity {{identity.uid}}" left-buttons="leftButtons">
+<ion-view view-title="{{identity.uid}}" left-buttons="leftButtons">
 <ion-content>
     <div class="scroll">
         <div class="list">
             <span class="item item-icon-left">
                 <i class="icon ion-person"></i>
-                Uid
-                <span class="badge badge-royal">{{identity.uid}}</span>
-            </span>
-
-            <span class="item item-icon-left">
-                <i class="icon ion-key"></i>
-                Public key
-                <span class="badge">{{identity.pub | formatPubkey}}</span>
+                <h2>{{identity.uid}}</h2>
+                <p>public key: {{identity.pub | formatPubkey}}</p>
+                <span class="badge"></span>
             </span>
 
             <span class="item item-icon-left">