diff --git a/ionic.project b/ionic.project
index 1114d8e80333f332780b7eb97d73c144889486e1..2aae2082ec11a1d2c7849726dc195e913886f1af 100644
--- a/ionic.project
+++ b/ionic.project
@@ -24,4 +24,4 @@
       "version": "12.41.296.5"
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js
index c4cc0e83993c06cb563929b00eda8bbbca7ac550..70ec7390052fc58f9bc29aef3366acbed76573d6 100644
--- a/www/js/controllers/currency-controllers.js
+++ b/www/js/controllers/currency-controllers.js
@@ -100,7 +100,7 @@ function CurrencyLookupController($scope, $state, UIUtils, csCurrency) {
   };
 }
 
-function CurrencyViewController($scope, $q, BMA, UIUtils, csSettings, csCurrency) {
+function CurrencyViewController($scope, $q, $timeout, BMA, UIUtils, csSettings, csCurrency, csNetwork) {
   $scope.formData = {
     useRelative: csSettings.data.useRelative,
     currency: '',
@@ -120,49 +120,59 @@ function CurrencyViewController($scope, $q, BMA, UIUtils, csSettings, csCurrency
     stepMax: 0,
     xpercent: 0,
     durationFromLastUD: 0,
+    blockUid: null
   };
   $scope.node = null;
   $scope.loading = true;
   $scope.screen = UIUtils.screen;
 
   $scope.$on('$ionicView.enter', function(e, state) {
-    if (state.stateParams && state.stateParams.name) { // Load by name
-      csCurrency.searchByName(state.stateParams.name)
-      .then(function(currency){
-        $scope.load(currency);
-      });
-    }
-    else {
-      csCurrency.all()
-      .then(function (currencies) {
-        if (currencies && currencies.length > 0) {
-          $scope.load(currencies[0]);
+    if ($scope.loading) { // run only once (first enter)
+      if (state.stateParams && state.stateParams.name) { // Load by name
+        csCurrency.searchByName(state.stateParams.name)
+        .then(function(currency){
+          $scope.init(currency);
+        });
+      }
+      else {
+        csCurrency.default()
+        .then(function (currency) {
+          $scope.init(currency);
+        })
+        .catch(UIUtils.onError('ERROR.GET_CURRENCY_FAILED'));
+      }
+
+      csNetwork.api.data.on.mainBlockChanged($scope, function(data) {
+        if ($scope.loading) return;
+        if ($scope.formData.blockUid !== data.mainBuid) {
+          console.debug("[currency] Updating parameters UI (new main block detected)");
+          $timeout($scope.load, 1000 /*waiting propagation to requested node*/);
         }
-      })
-      .catch(UIUtils.onError('ERROR.GET_CURRENCY_FAILED'));
+      });
     }
   });
 
-  $scope.load = function(currency) {
+  $scope.init = function(currency) {
     $scope.formData.currency = currency.name;
     $scope.node = !BMA.node.same(currency.peer.host, currency.peer.port) ?
       BMA.instance(currency.peer.host, currency.peer.port) : BMA;
+
     UIUtils.loading.show();
 
-    // Load currency parameters
-    $scope.loadParameter();
+    // Load data
+    $scope.load()
 
-    // Show help tip
-    $scope.showHelpTip();
+      // Show help tip
+      .then($scope.showHelpTip);
   };
 
-  $scope.loadParameter = function() {
+  $scope.load = function() {
     if (!$scope.node) {
       return;
     }
+
     // Load data from node
-    var data = {};
-    var M, lastUDTime;
+    var data = {}, M, lastUDTime, now = new Date().getTime();
     return $q.all([
 
       // Get the currency parameters
@@ -186,6 +196,7 @@ function CurrencyViewController($scope, $q, BMA, UIUtils, csSettings, csCurrency
           data.N = block.membersCount;
           data.medianTime  = block.medianTime;
           data.difficulty  = block.powMin;
+          data.blockUid = [block.number, block.hash].join('-');
         })
         .catch(function(err){
           // Special case for currency init (root block not exists): use fixed values
@@ -231,13 +242,15 @@ function CurrencyViewController($scope, $q, BMA, UIUtils, csSettings, csCurrency
       data.MoverN = (Mprev ? Mprev : M/*need at currency start only*/) / data.Nprev;
       data.UD = data.currentUD;
       data.durationFromLastUD = lastUDTime ? data.medianTime - lastUDTime : 0;
+      data.useRelative = $scope.formData.useRelative;
 
       // Apply to formData
       angular.copy(data, $scope.formData);
 
+      console.debug("[currency] Parameters loaded in " + (new Date().getTime() - now) + 'ms' );
       $scope.loading = false;
       $scope.$broadcast('$$rebind::' + 'rebind'); // force bind of currency name
-      UIUtils.loading.hide();
+      return UIUtils.loading.hide();
     })
     .catch(function(err) {
       $scope.loading = false;
diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js
index 4066d69c8d1d4a41d41e3db9dfaa91a7efdd17ef..46fbfffe667fcad938b734c830799cbbaf269df7 100644
--- a/www/js/controllers/network-controllers.js
+++ b/www/js/controllers/network-controllers.js
@@ -76,7 +76,7 @@ function NetworkLookupController($scope, $timeout, $state, $ionicPopover, BMA, U
         if (!refreshing) {
           refreshing = true;
           $timeout(function() { // Timeout avoid to quick updates
-            console.debug("Updating UI Peers");
+            console.debug("[peers] Updating UI");
             $scope.search.results = data.peers;
             $scope.search.memberPeersCount = data.memberPeersCount;
             $scope.search.loading = csNetwork.isBusy();
diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js
index 5ac3ed14530a06b6bb2e57b5ec41a7a12e30c8ae..2c3583082158a9120acdc2141a1654d72a6dde0c 100644
--- a/www/js/services/bma-services.js
+++ b/www/js/services/bma-services.js
@@ -346,4 +346,696 @@ angular.module('cesium.bma.services', ['ngResource', 'cesium.http.services', 'ce
 
   return service;
 })
+
+  .factory('BMA', function($q, csSettings, csHttp, csCache, $rootScope, $timeout) {
+    'ngInject';
+
+    function factory(host, port, cacheEnable) {
+
+      function exact(regexpContent) {
+        return new RegExp("^" + regexpContent + "$");
+      }
+
+      var
+        regex = {
+          USER_ID: "[A-Za-z0-9_-]+",
+          CURRENCY: "[A-Za-z0-9_-]+",
+          PUBKEY: "[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}",
+          COMMENT: "[ a-zA-Z0-9-_:/;*\\[\\]()?!^\\+=@&~#{}|\\\\<>%.]*",
+          // duniter://[uid]:[pubkey]@[host]:[port]
+          URI_WITH_AT: "duniter://(?:([A-Za-z0-9_-]+):)?([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44})@([a-zA-Z0-9-.]+.[ a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+)",
+          URI_WITH_PATH: "duniter://([a-zA-Z0-9-.]+.[a-zA-Z0-9-_:.]+)/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44})(?:/([A-Za-z0-9_-]+))?"
+        },
+        errorCodes = {
+          REVOCATION_ALREADY_REGISTERED: 1002,
+          HTTP_LIMITATION: 1006,
+          IDENTITY_SANDBOX_FULL: 1007,
+          NO_MATCHING_IDENTITY: 2001,
+          UID_ALREADY_USED: 2003,
+          NO_MATCHING_MEMBER: 2004,
+          NO_IDTY_MATCHING_PUB_OR_UID: 2021,
+          MEMBERSHIP_ALREADY_SEND: 2007,
+          NO_CURRENT_BLOCK: 2010,
+          BLOCK_NOT_FOUND: 2011,
+          TX_ALREADY_PROCESSED: 2030
+        },
+        constants = {
+          PROTOCOL_VERSION: 10,
+          ROOT_BLOCK_HASH: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855',
+          LIMIT_REQUEST_COUNT: 5, // simultaneous async request to a Duniter node
+          LIMIT_REQUEST_DELAY: 1000 // time (in second) to wait between to call of a rest request
+        };
+
+      var exports = {
+        errorCodes: errorCodes,
+        constants: constants,
+        regex: {
+          USER_ID: exact(regex.USER_ID),
+          COMMENT: exact(regex.COMMENT),
+          PUBKEY: exact(regex.PUBKEY),
+          CURRENCY: exact(regex.CURRENCY),
+          URI: exact(regex.URI)
+        },
+        node: {
+          server: csHttp.getServer(host, port),
+          host: host,
+          port: port,
+          summary: csHttp.getWithCache(host, port, '/node/summary', csHttp.cache.LONG),
+          same: function(host2, port2) {
+            return host2 == host && ((!port && !port2) || (port == port2));
+          }
+        },
+        network: {
+          peering: {
+            peers: csHttp.get(host, port, '/network/peering/peers')
+          },
+          peers: csHttp.get(host, port, '/network/peers')
+        },
+        wot: {
+          lookup: csHttp.get(host, port, '/wot/lookup/:search'),
+          certifiedBy: csHttp.get(host, port, '/wot/certified-by/:pubkey'),
+          certifiersOf: csHttp.get(host, port, '/wot/certifiers-of/:pubkey'),
+          member: {
+            all: cacheEnable ? csHttp.getWithCache(host, port, '/wot/members') : csHttp.get(host, port, '/wot/members'),
+            pending: csHttp.get(host, port, '/wot/pending')
+          },
+          requirements: csHttp.get(host, port, '/wot/requirements/:pubkey'),
+          add: csHttp.post(host, port, '/wot/add'),
+          certify: csHttp.post(host, port, '/wot/certify'),
+          revoke: csHttp.post(host, port, '/wot/revoke')
+        },
+        blockchain: {
+          parameters: csHttp.getWithCache(host, port, '/blockchain/parameters', csHttp.cache.LONG),
+          block: cacheEnable ? csHttp.getWithCache(host, port, '/blockchain/block/:block', csHttp.cache.SHORT) : csHttp.get(host, port, '/blockchain/block/:block'),
+          current: csHttp.get(host, port, '/blockchain/current'),
+          membership: csHttp.post(host, port, '/blockchain/membership'),
+          stats: {
+            ud: cacheEnable ? csHttp.getWithCache(host, port, '/blockchain/with/ud', csHttp.cache.SHORT) : csHttp.get(host, port, '/blockchain/with/ud'),
+            tx: csHttp.get(host, port, '/blockchain/with/tx'),
+            newcomers: csHttp.get(host, port, '/blockchain/with/newcomers'),
+            hardship: csHttp.get(host, port, '/blockchain/hardship/:pubkey')
+          }
+        },
+        tx: {
+          sources: csHttp.get(host, port, '/tx/sources/:pubkey'),
+          process: csHttp.post(host, port, '/tx/process'),
+          history: {
+            all: csHttp.get(host, port, '/tx/history/:pubkey'),
+            times: cacheEnable ? csHttp.getWithCache(host, port, '/tx/history/:pubkey/times/:from/:to') : csHttp.get(host, port, '/tx/history/:pubkey/times/:from/:to'),
+            timesNoCache: csHttp.get(host, port, '/tx/history/:pubkey/times/:from/:to'),
+            blocks: cacheEnable ? csHttp.getWithCache(host, port, '/tx/history/:pubkey/blocks/:from/:to') : csHttp.get(host, port, '/tx/history/:pubkey/blocks/:from/:to'),
+            pending: csHttp.get(host, port, '/tx/history/:pubkey/pending')
+          }
+        },
+        ud: {
+          history: csHttp.get(host, port, '/ud/history/:pubkey')
+        },
+        uri: {},
+        raw: {
+
+        }
+      };
+
+      exports.copy = function(otherNode) {
+        if (!!this.instance) { // if main service impl
+          var instance = this.instance; // keep factory
+          csCache.clearAll(); // clean all caches
+          angular.copy(otherNode, this);
+          this.instance = instance;
+        }
+        else {
+          angular.copy(otherNode, this);
+        }
+      };
+
+      exports.wot.member.uids = function() {
+        return exports.wot.member.all()
+          .then(function(res){
+            return res.results.reduce(function(res, member){
+              res[member.pubkey] = member.uid;
+              return res;
+            }, {});
+          });
+      };
+
+      exports.wot.member.get = function(pubkey) {
+        return exports.wot.member.uids()
+          .then(function(memberUidsByPubkey){
+            var uid = memberUidsByPubkey[pubkey];
+            return {
+              pubkey: pubkey,
+              uid: (uid ? uid : null)
+            };
+          });
+      };
+
+      /**
+       * Return all expected blocks
+       * @param blockNumbers a rray of block number
+       */
+      exports.blockchain.blocks = function(blockNumbers){
+        return exports.raw.blocksRecursive(blockNumbers, 0, exports.constants.LIMIT_REQUEST_COUNT);
+      };
+
+      exports.raw.blocksRecursive = function(blockNumbers, offset, size) {
+        return $q(function(resolve, reject) {
+          var result = [];
+          var jobs = [];
+          _.each(blockNumbers.slice(offset, offset+size), function(blockNumber) {
+            jobs.push(
+              exports.blockchain.block({block: blockNumber})
+                .then(function(block){
+                  if (!block) return;
+                  result.push(block);
+                })
+            );
+          });
+
+          $q.all(jobs)
+            .then(function() {
+              if (offset < blockNumbers.length - 1) {
+                $timeout(function() {
+                  exports.raw.blocksRecursive(blockNumbers, offset+size, size)
+                    .then(function(blocks) {
+                      if (!blocks || !blocks.length) {
+                        resolve(result);
+                        return;
+                      }
+                      resolve(result.concat(blocks));
+                    })
+                    .catch(function(err) {
+                      reject(err);
+                    });
+                }, exports.constants.LIMIT_REQUEST_DELAY);
+              }
+              else {
+                resolve(result);
+              }
+            })
+            .catch(function(err){
+              if (err && err.ucode === errorCodes.HTTP_LIMITATION) {
+                resolve(result);
+              }
+              else {
+                reject(err);
+              }
+            });
+        });
+      };
+
+      exports.blockchain.lastUd = function() {
+        return exports.blockchain.stats.ud()
+          .then(function(res) {
+            if (!res.result.blocks || !res.result.blocks.length) {
+              return null;
+            }
+            var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1];
+            return exports.blockchain.block({block: lastBlockWithUD})
+              .then(function(block){
+                return (block.unitbase > 0) ? block.dividend * Math.pow(10, block.unitbase) : block.dividend;
+              });
+          });
+      };
+
+      exports.uri.parse = function(uri) {
+        return $q(function(resolve, reject) {
+          // If pubkey: not need to parse
+          if (exact(regex.PUBKEY).test(uri)) {
+            resolve({
+              pubkey: uri
+            });
+          }
+          else if(uri.startsWith('duniter://')) {
+            var parser = csHttp.uri.parse(uri),
+              pubkey,
+              uid,
+              currency = parser.host.indexOf('.') === -1 ? parser.host : null,
+              host = parser.host.indexOf('.') !== -1 ? parser.host : null;
+            if (parser.username) {
+              if (parser.password) {
+                uid = parser.username;
+                pubkey = parser.password;
+              }
+              else {
+                pubkey = parser.username;
+              }
+            }
+            if (parser.pathname) {
+              var paths = parser.pathname.split('/');
+              var pathCount = !paths ? 0 : paths.length;
+              var index = 0;
+              if (!currency && pathCount > index) {
+                currency = paths[index++];
+              }
+              if (!pubkey && pathCount > index) {
+                pubkey = paths[index++];
+              }
+              if (!uid && pathCount > index) {
+                uid = paths[index++];
+              }
+              if (pathCount > index) {
+                reject( {message: 'Bad Duniter URI format. Invalid path (incomplete or redundant): '+ parser.pathname}); return;
+              }
+            }
+
+            if (!currency){
+              if (host) {
+                csHttp.get(host + '/blockchain/parameters')()
+                  .then(function(parameters){
+                    resolve({
+                      uid: uid,
+                      pubkey: pubkey,
+                      host: host,
+                      currency: parameters.currency
+                    });
+                  })
+                  .catch(function(err) {
+                    console.log(err);
+                    reject({message: 'Could not get node parameter. Currency could not be retrieve'});
+                  });
+              }
+              else {
+                reject({message: 'Bad Duniter URI format. Missing currency name (or node address).'}); return;
+              }
+            }
+            else {
+              if (!host) {
+                resolve({
+                  uid: uid,
+                  pubkey: pubkey,
+                  currency: currency
+                });
+              }
+
+              // Check if currency are the same (between node and uri)
+              return csHttp.get(host + '/blockchain/parameters')()
+                .then(function(parameters){
+                  if (parameters.currency !== currency) {
+                    reject( {message: "Node's currency ["+parameters.currency+"] does not matched URI's currency ["+currency+"]."}); return;
+                  }
+                  resolve({
+                    uid: uid,
+                    pubkey: pubkey,
+                    host: host,
+                    currency: currency
+                  });
+                });
+            }
+          }
+          else {
+            throw {message: 'Bad URI format: ' + uri};
+          }
+        })
+
+        // Check values against regex
+          .then(function(result) {
+            if (result.pubkey && !(exact(regex.PUBKEY).test(result.pubkey))) {
+              reject({message: "Invalid pubkey format [" + result.pubkey + "]"}); return;
+            }
+            if (result.uid && !(exact(regex.USER_ID).test(result.uid))) {
+              reject({message: "Invalid uid format [" + result.uid + "]"}); return;
+            }
+            if (result.currency && !(exact(regex.CURRENCY).test(result.currency))) {
+              reject({message: "Invalid currency format ["+result.currency+"]"}); return;
+            }
+            return result;
+          });
+      };
+
+      exports.websocket = {
+        block: function() {
+          return csHttp.ws('ws://' + exports.node.server + '/ws/block');
+        },
+        peer: function() {
+          return csHttp.ws('ws://' + exports.node.server + '/ws/peer');
+        },
+        close : csHttp.closeAllWs
+      };
+
+      return exports;
+    }
+
+    var service = factory(csSettings.data.node.host, csSettings.data.node.port, true /*cache*/);
+    service.instance = factory;
+
+    // Listen settings changes
+    csSettings.api.data.on.changed($rootScope, function(settings) {
+
+      var nodeServer = csHttp.getServer(settings.node.host, settings.node.port);
+      if (nodeServer != service.node.server) {
+        var newService = factory(settings.node.host, settings.node.port, true /*cache*/);
+        service.copy(newService); // reload service
+      }
+
+    });
+
+    return service;
+  })
+
+  .factory('BMA', function($q, csSettings, csHttp, csCache, $rootScope, $timeout) {
+    'ngInject';
+
+    function factory(host, port, cacheEnable) {
+
+      function exact(regexpContent) {
+        return new RegExp("^" + regexpContent + "$");
+      }
+
+      var
+        regex = {
+          USER_ID: "[A-Za-z0-9_-]+",
+          CURRENCY: "[A-Za-z0-9_-]+",
+          PUBKEY: "[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}",
+          COMMENT: "[ a-zA-Z0-9-_:/;*\\[\\]()?!^\\+=@&~#{}|\\\\<>%.]*",
+          // duniter://[uid]:[pubkey]@[host]:[port]
+          URI_WITH_AT: "duniter://(?:([A-Za-z0-9_-]+):)?([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44})@([a-zA-Z0-9-.]+.[ a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+)",
+          URI_WITH_PATH: "duniter://([a-zA-Z0-9-.]+.[a-zA-Z0-9-_:.]+)/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44})(?:/([A-Za-z0-9_-]+))?"
+        },
+        errorCodes = {
+          REVOCATION_ALREADY_REGISTERED: 1002,
+          HTTP_LIMITATION: 1006,
+          IDENTITY_SANDBOX_FULL: 1007,
+          NO_MATCHING_IDENTITY: 2001,
+          UID_ALREADY_USED: 2003,
+          NO_MATCHING_MEMBER: 2004,
+          NO_IDTY_MATCHING_PUB_OR_UID: 2021,
+          MEMBERSHIP_ALREADY_SEND: 2007,
+          NO_CURRENT_BLOCK: 2010,
+          BLOCK_NOT_FOUND: 2011,
+          TX_ALREADY_PROCESSED: 2030
+        },
+        constants = {
+          PROTOCOL_VERSION: 10,
+          ROOT_BLOCK_HASH: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855',
+          LIMIT_REQUEST_COUNT: 5, // simultaneous async request to a Duniter node
+          LIMIT_REQUEST_DELAY: 1000 // time (in second) to wait between to call of a rest request
+        };
+
+      var exports = {
+        errorCodes: errorCodes,
+        constants: constants,
+        regex: {
+          USER_ID: exact(regex.USER_ID),
+          COMMENT: exact(regex.COMMENT),
+          PUBKEY: exact(regex.PUBKEY),
+          CURRENCY: exact(regex.CURRENCY),
+          URI: exact(regex.URI)
+        },
+        node: {
+          server: csHttp.getServer(host, port),
+          host: host,
+          port: port,
+          summary: csHttp.getWithCache(host, port, '/node/summary', csHttp.cache.LONG),
+          same: function(host2, port2) {
+            return host2 == host && ((!port && !port2) || (port == port2));
+          }
+        },
+        network: {
+          peering: {
+            peers: csHttp.get(host, port, '/network/peering/peers')
+          },
+          peers: csHttp.get(host, port, '/network/peers')
+        },
+        wot: {
+          lookup: csHttp.get(host, port, '/wot/lookup/:search'),
+          certifiedBy: csHttp.get(host, port, '/wot/certified-by/:pubkey'),
+          certifiersOf: csHttp.get(host, port, '/wot/certifiers-of/:pubkey'),
+          member: {
+            all: cacheEnable ? csHttp.getWithCache(host, port, '/wot/members') : csHttp.get(host, port, '/wot/members'),
+            pending: csHttp.get(host, port, '/wot/pending')
+          },
+          requirements: csHttp.get(host, port, '/wot/requirements/:pubkey'),
+          add: csHttp.post(host, port, '/wot/add'),
+          certify: csHttp.post(host, port, '/wot/certify'),
+          revoke: csHttp.post(host, port, '/wot/revoke')
+        },
+        blockchain: {
+          parameters: csHttp.getWithCache(host, port, '/blockchain/parameters', csHttp.cache.LONG),
+          block: cacheEnable ? csHttp.getWithCache(host, port, '/blockchain/block/:block', csHttp.cache.SHORT) : csHttp.get(host, port, '/blockchain/block/:block'),
+          current: csHttp.get(host, port, '/blockchain/current'),
+          membership: csHttp.post(host, port, '/blockchain/membership'),
+          stats: {
+            ud: cacheEnable ? csHttp.getWithCache(host, port, '/blockchain/with/ud', csHttp.cache.SHORT) : csHttp.get(host, port, '/blockchain/with/ud'),
+            tx: csHttp.get(host, port, '/blockchain/with/tx'),
+            newcomers: csHttp.get(host, port, '/blockchain/with/newcomers'),
+            hardship: csHttp.get(host, port, '/blockchain/hardship/:pubkey')
+          }
+        },
+        tx: {
+          sources: csHttp.get(host, port, '/tx/sources/:pubkey'),
+          process: csHttp.post(host, port, '/tx/process'),
+          history: {
+            all: csHttp.get(host, port, '/tx/history/:pubkey'),
+            times: cacheEnable ? csHttp.getWithCache(host, port, '/tx/history/:pubkey/times/:from/:to') : csHttp.get(host, port, '/tx/history/:pubkey/times/:from/:to'),
+            timesNoCache: csHttp.get(host, port, '/tx/history/:pubkey/times/:from/:to'),
+            blocks: cacheEnable ? csHttp.getWithCache(host, port, '/tx/history/:pubkey/blocks/:from/:to') : csHttp.get(host, port, '/tx/history/:pubkey/blocks/:from/:to'),
+            pending: csHttp.get(host, port, '/tx/history/:pubkey/pending')
+          }
+        },
+        ud: {
+          history: csHttp.get(host, port, '/ud/history/:pubkey')
+        },
+        uri: {},
+        raw: {
+
+        }
+      };
+
+      exports.copy = function(otherNode) {
+        if (!!this.instance) { // if main service impl
+          var instance = this.instance; // keep factory
+          csCache.clearAll(); // clean all caches
+          angular.copy(otherNode, this);
+          this.instance = instance;
+        }
+        else {
+          angular.copy(otherNode, this);
+        }
+      };
+
+      exports.wot.member.uids = function() {
+        return exports.wot.member.all()
+          .then(function(res){
+            return res.results.reduce(function(res, member){
+              res[member.pubkey] = member.uid;
+              return res;
+            }, {});
+          });
+      };
+
+      exports.wot.member.get = function(pubkey) {
+        return exports.wot.member.uids()
+          .then(function(memberUidsByPubkey){
+            var uid = memberUidsByPubkey[pubkey];
+            return {
+              pubkey: pubkey,
+              uid: (uid ? uid : null)
+            };
+          });
+      };
+
+      /**
+       * Return all expected blocks
+       * @param blockNumbers a rray of block number
+       */
+      exports.blockchain.blocks = function(blockNumbers){
+        return exports.raw.blocksRecursive(blockNumbers, 0, exports.constants.LIMIT_REQUEST_COUNT);
+      };
+
+      exports.raw.blocksRecursive = function(blockNumbers, offset, size) {
+        return $q(function(resolve, reject) {
+          var result = [];
+          var jobs = [];
+          _.each(blockNumbers.slice(offset, offset+size), function(blockNumber) {
+            jobs.push(
+              exports.blockchain.block({block: blockNumber})
+                .then(function(block){
+                  if (!block) return;
+                  result.push(block);
+                })
+            );
+          });
+
+          $q.all(jobs)
+            .then(function() {
+              if (offset < blockNumbers.length - 1) {
+                $timeout(function() {
+                  exports.raw.blocksRecursive(blockNumbers, offset+size, size)
+                    .then(function(blocks) {
+                      if (!blocks || !blocks.length) {
+                        resolve(result);
+                        return;
+                      }
+                      resolve(result.concat(blocks));
+                    })
+                    .catch(function(err) {
+                      reject(err);
+                    });
+                }, exports.constants.LIMIT_REQUEST_DELAY);
+              }
+              else {
+                resolve(result);
+              }
+            })
+            .catch(function(err){
+              if (err && err.ucode === errorCodes.HTTP_LIMITATION) {
+                resolve(result);
+              }
+              else {
+                reject(err);
+              }
+            });
+        });
+      };
+
+      exports.blockchain.lastUd = function() {
+        return exports.blockchain.stats.ud()
+          .then(function(res) {
+            if (!res.result.blocks || !res.result.blocks.length) {
+              return null;
+            }
+            var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1];
+            return exports.blockchain.block({block: lastBlockWithUD})
+              .then(function(block){
+                return (block.unitbase > 0) ? block.dividend * Math.pow(10, block.unitbase) : block.dividend;
+              });
+          });
+      };
+
+      exports.uri.parse = function(uri) {
+        return $q(function(resolve, reject) {
+          // If pubkey: not need to parse
+          if (exact(regex.PUBKEY).test(uri)) {
+            resolve({
+              pubkey: uri
+            });
+          }
+          else if(uri.startsWith('duniter://')) {
+            var parser = csHttp.uri.parse(uri),
+              pubkey,
+              uid,
+              currency = parser.host.indexOf('.') === -1 ? parser.host : null,
+              host = parser.host.indexOf('.') !== -1 ? parser.host : null;
+            if (parser.username) {
+              if (parser.password) {
+                uid = parser.username;
+                pubkey = parser.password;
+              }
+              else {
+                pubkey = parser.username;
+              }
+            }
+            if (parser.pathname) {
+              var paths = parser.pathname.split('/');
+              var pathCount = !paths ? 0 : paths.length;
+              var index = 0;
+              if (!currency && pathCount > index) {
+                currency = paths[index++];
+              }
+              if (!pubkey && pathCount > index) {
+                pubkey = paths[index++];
+              }
+              if (!uid && pathCount > index) {
+                uid = paths[index++];
+              }
+              if (pathCount > index) {
+                reject( {message: 'Bad Duniter URI format. Invalid path (incomplete or redundant): '+ parser.pathname}); return;
+              }
+            }
+
+            if (!currency){
+              if (host) {
+                csHttp.get(host + '/blockchain/parameters')()
+                  .then(function(parameters){
+                    resolve({
+                      uid: uid,
+                      pubkey: pubkey,
+                      host: host,
+                      currency: parameters.currency
+                    });
+                  })
+                  .catch(function(err) {
+                    console.log(err);
+                    reject({message: 'Could not get node parameter. Currency could not be retrieve'});
+                  });
+              }
+              else {
+                reject({message: 'Bad Duniter URI format. Missing currency name (or node address).'}); return;
+              }
+            }
+            else {
+              if (!host) {
+                resolve({
+                  uid: uid,
+                  pubkey: pubkey,
+                  currency: currency
+                });
+              }
+
+              // Check if currency are the same (between node and uri)
+              return csHttp.get(host + '/blockchain/parameters')()
+                .then(function(parameters){
+                  if (parameters.currency !== currency) {
+                    reject( {message: "Node's currency ["+parameters.currency+"] does not matched URI's currency ["+currency+"]."}); return;
+                  }
+                  resolve({
+                    uid: uid,
+                    pubkey: pubkey,
+                    host: host,
+                    currency: currency
+                  });
+                });
+            }
+          }
+          else {
+            throw {message: 'Bad URI format: ' + uri};
+          }
+        })
+
+        // Check values against regex
+          .then(function(result) {
+            if (result.pubkey && !(exact(regex.PUBKEY).test(result.pubkey))) {
+              reject({message: "Invalid pubkey format [" + result.pubkey + "]"}); return;
+            }
+            if (result.uid && !(exact(regex.USER_ID).test(result.uid))) {
+              reject({message: "Invalid uid format [" + result.uid + "]"}); return;
+            }
+            if (result.currency && !(exact(regex.CURRENCY).test(result.currency))) {
+              reject({message: "Invalid currency format ["+result.currency+"]"}); return;
+            }
+            return result;
+          });
+      };
+
+      exports.websocket = {
+        block: function() {
+          return csHttp.ws('ws://' + exports.node.server + '/ws/block');
+        },
+        peer: function() {
+          return csHttp.ws('ws://' + exports.node.server + '/ws/peer');
+        },
+        close : csHttp.closeAllWs
+      };
+
+      return exports;
+    }
+
+    var service = factory(csSettings.data.node.host, csSettings.data.node.port, true /*cache*/);
+    service.instance = factory;
+
+    // Listen settings changes
+    csSettings.api.data.on.changed($rootScope, function(settings) {
+
+      var nodeServer = csHttp.getServer(settings.node.host, settings.node.port);
+      if (nodeServer != service.node.server) {
+        var newService = factory(settings.node.host, settings.node.port, true /*cache*/);
+        service.copy(newService); // reload service
+      }
+
+    });
+
+    return service;
+  })
+
+
 ;
diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js
index 474e8099326df311e7c28e89a047f2603817adc5..7cd07a39313f2f6e2b54c330ed8cf83c2059bb0e 100644
--- a/www/js/services/network-services.js
+++ b/www/js/services/network-services.js
@@ -1,7 +1,7 @@
 
-angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.services'])
+angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.services', 'cesium.http.services'])
 
-.factory('csNetwork', function($rootScope, $q, $interval, $timeout, BMA, Api, csSettings, UIUtils) {
+.factory('csNetwork', function($rootScope, $q, $interval, $timeout, BMA, csHttp, Api, csSettings, UIUtils) {
   'ngInject';
 
   factory = function(id) {
@@ -64,6 +64,20 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
         return data.knownBlocks;
       },
 
+      newLightBMA = function(peer) {
+        return {
+          node: {
+            summary: csHttp.getWithCache(peer.getHost(), peer.getPort(), '/node/summary', csHttp.cache.LONG)
+          },
+          blockchain: {
+            current: csHttp.get(peer.getHost(), peer.getPort(), '/blockchain/current'),
+            stats: {
+              hardship: csHttp.get(peer.getHost(), peer.getPort(), '/blockchain/hardship/:pubkey')
+            }
+          }
+        };
+      },
+
       loadPeers = function() {
         data.knownPeers = {};
         data.peers = [];
@@ -157,7 +171,7 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
         // Apply filter
         if (!applyPeerFilter(peer)) return $q.when();
 
-        var node = new BMA.instance(peer.getHost(), peer.getPort(), false);
+        var node = newLightBMA(peer);
 
         // Get current block
         return node.blockchain.current()
@@ -257,8 +271,9 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
           score += (-1       * (peer.uid ? peer.uid.charCodeAt(0) : 999)); // alphabetical order
           return -score;
         });
-        if (updateMainBuid) {
+        if (updateMainBuid && mainBlock.buid) {
           data.mainBuid = mainBlock.buid;
+          console.log(data.mainBuid);
           api.data.raise.mainBlockChanged(data); // raise event
         }
         api.data.raise.changed(data); // raise event
diff --git a/www/templates/currency/items_parameters.html b/www/templates/currency/items_parameters.html
index f4eb74f8e27c7a16c3b3f5a693672cab676ed1ca..665a0d95ba8a58f59aa9fa5b010e505e410c0681 100644
--- a/www/templates/currency/items_parameters.html
+++ b/www/templates/currency/items_parameters.html
@@ -44,7 +44,7 @@
 
         <div class="item item-toggle dark">
             <span translate>COMMON.BTN_RELATIVE_UNIT</span>
-            <label class="toggle toggle-royal" id="helptip-currency-change-unit" ng-if="!loading">
+            <label class="toggle toggle-royal" id="helptip-currency-change-unit">
                 <input type="checkbox" ng-model="formData.useRelative">
                 <div class="track">
                     <div class="handle"></div>