From 74eeeae465902f4a28d6167a21a07fcc034394f6 Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Wed, 28 Jun 2017 18:02:20 +0200
Subject: [PATCH] [enh] enable to browse blockhain of any peers

---
 www/i18n/locale-en-GB.json                    |  12 +-
 www/i18n/locale-en.json                       |  12 +-
 www/i18n/locale-es-ES.json                    |  14 ++-
 www/i18n/locale-fr-FR.json                    |   5 +-
 www/i18n/locale-nl-NL.json                    |   6 +-
 www/js/controllers/blockchain-controllers.js  | 118 +++++++++++++++---
 .../templates/network/view_peer_extend.html   |   3 +-
 www/templates/blockchain/list_blocks_lg.html  |   2 +-
 www/templates/network/view_peer.html          |  14 ++-
 9 files changed, 150 insertions(+), 36 deletions(-)

diff --git a/www/i18n/locale-en-GB.json b/www/i18n/locale-en-GB.json
index 546f7a0c1..736b72141 100644
--- a/www/i18n/locale-en-GB.json
+++ b/www/i18n/locale-en-GB.json
@@ -108,14 +108,13 @@
     "TITLE": "Cesium",
     "MESSAGE": "Welcome to the Cesium Application!<br/>Watch your <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> wallets in real time.",
     "MESSAGE_SHORT": "Watch your <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> wallets<br/>in real time!",
-    "BTN_REGISTRY": "Registry",
-    "BTN_MARKET": "Market place",
     "BTN_CURRENCY": "Explore currency",
     "BTN_ABOUT": "about",
     "BTN_HELP": "Help",
     "REPORT_ISSUE": "Report an issue",
     "NOT_YOUR_ACCOUNT_QUESTION" : "You do not own the account <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b>?",
-    "BTN_CHANGE_ACCOUNT": "Disconnect this account"
+    "BTN_CHANGE_ACCOUNT": "Disconnect this account",
+    "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or change node <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in the settings</a>."
   },
   "SETTINGS": {
     "TITLE": "Settings",
@@ -280,6 +279,7 @@
       "TITLE": "Peer",
       "OWNER": "Owned by ",
       "SHOW_RAW_PEERING": "See peering document",
+      "LAST_BLOCKS": "Last blocks",
       "KNOWN_PEERS": "Known peers :",
       "GENERAL_DIVIDER": "General information",
       "ERROR": {
@@ -341,6 +341,9 @@
       "ERROR": "Received certifications in error",
       "SENTRY_MEMBER": "Referring member"
     },
+    "OPERATIONS": {
+      "TITLE": "{{uid}} - Operations"
+    },
     "GIVEN_CERTIFICATIONS": {
       "TITLE": "{{uid}} - Certifications sent",
       "SUMMARY": "Sent certifications",
@@ -593,7 +596,8 @@
     "IDENTITY_WILL_MISSING_CERTIFICATIONS": "This identity will soon lack certification (at least {{willNeedCertificationCount}}).",
     "REVOCATION_SENT": "Revocation sent successfully",
     "REVOCATION_SENT_WAITING_PROCESS": "Revocation <b>has been sent successfully</b>. It is awaiting processing.",
-    "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)"
+    "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)",
+    "EMPTY_TX_HISTORY": "No operations to export"
   },
   "CONFIRM": {
     "POPUP_TITLE": "<b>Confirmation</b>",
diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json
index c9c3e718e..adb4726b2 100644
--- a/www/i18n/locale-en.json
+++ b/www/i18n/locale-en.json
@@ -108,14 +108,13 @@
     "TITLE": "Cesium",
     "MESSAGE": "Welcome to the Cesium Application!<br/>Watch your <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> wallets in real time.",
     "MESSAGE_SHORT": "Watch your <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> wallets<br/>in real time!",
-    "BTN_REGISTRY": "Registry",
-    "BTN_MARKET": "Market place",
     "BTN_CURRENCY": "Explore currency",
     "BTN_ABOUT": "about",
     "BTN_HELP": "Help",
     "REPORT_ISSUE": "Report an issue",
     "NOT_YOUR_ACCOUNT_QUESTION" : "You do not own the account <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b>?",
-    "BTN_CHANGE_ACCOUNT": "Disconnect this account"
+    "BTN_CHANGE_ACCOUNT": "Disconnect this account",
+    "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or change node <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in the settings</a>."
   },
   "SETTINGS": {
     "TITLE": "Settings",
@@ -280,6 +279,7 @@
       "TITLE": "Peer",
       "OWNER": "Owned by ",
       "SHOW_RAW_PEERING": "See peering document",
+      "LAST_BLOCKS": "Last blocks",
       "KNOWN_PEERS": "Known peers :",
       "GENERAL_DIVIDER": "General information",
       "ERROR": {
@@ -341,6 +341,9 @@
       "ERROR": "Received certifications in error",
       "SENTRY_MEMBER": "Referring member"
     },
+    "OPERATIONS": {
+      "TITLE": "{{uid}} - Operations"
+    },
     "GIVEN_CERTIFICATIONS": {
       "TITLE": "{{uid}} - Certifications sent",
       "SUMMARY": "Sent certifications",
@@ -593,7 +596,8 @@
     "IDENTITY_WILL_MISSING_CERTIFICATIONS": "This identity will soon lack certification (at least {{willNeedCertificationCount}}).",
     "REVOCATION_SENT": "Revocation sent successfully",
     "REVOCATION_SENT_WAITING_PROCESS": "Revocation <b>has been sent successfully</b>. It is awaiting processing.",
-    "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)"
+    "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)",
+    "EMPTY_TX_HISTORY": "No operations to export"
   },
   "CONFIRM": {
     "POPUP_TITLE": "<b>Confirmation</b>",
diff --git a/www/i18n/locale-es-ES.json b/www/i18n/locale-es-ES.json
index ae7250e31..ed14f7c0e 100644
--- a/www/i18n/locale-es-ES.json
+++ b/www/i18n/locale-es-ES.json
@@ -108,14 +108,13 @@
     "TITLE": "Cesium",
     "MESSAGE": "Bienvenida en la aplicación Cesium !<br/>Sigue sus cuentas <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> en tiempo real.",
     "MESSAGE_SHORT": "Sigue sus cuentas <a href=\"http://duniter.org\" target=\"_system\">Duniter</a><br/>en tiempo real !",
-    "BTN_REGISTRY": "Anuario",
-    "BTN_MARKET": "Ofertas/demandas",
     "BTN_CURRENCY": "Explorar la moneda",
     "BTN_ABOUT": "A propósito",
     "BTN_HELP": "Ayuda en línea",
     "REPORT_ISSUE": "anomalía",
     "NOT_YOUR_ACCOUNT_QUESTION" : "Usted no es dueño de la cuenta <<b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b>?",
-    "BTN_CHANGE_ACCOUNT": "Desconectar esta cuenta"
+    "BTN_CHANGE_ACCOUNT": "Desconectar esta cuenta",
+    "CONNECTION_ERROR": "Nodo <b>{{servidor}}</b> inalcanzable o dirección no válida.<br/><br/>Compruebe su conexión a Internet, o nodo de conmutación <a class=\"positive\" ng-click=\"doQuickFix('settings')\">en los parámetros</a>."
   },
   "SETTINGS": {
     "TITLE": "Configuraciónes",
@@ -279,7 +278,8 @@
     "VIEW": {
       "TITLE": "Nodo",
       "OWNER": "Propiedad de ",
-      "SHOW_RAW_PEERING": "Ver la tarjeta de red",
+      "SHOW_RAW_PEERING": "Ver la tarjeta de red",,
+      "LAST_BLOCKS": "Bloques recientes",
       "KNOWN_PEERS": "Nodos conocidos :",
       "GENERAL_DIVIDER": "Informaciónes generales",
       "ERROR": {
@@ -341,6 +341,9 @@
       "ERROR": "Certificaciónes recibidas por error",
       "SENTRY_MEMBER": "Miembro referente"
     },
+    "OPERATIONS": {
+      "TITLE": "{{uid}} - Operaciones"
+    },
     "GIVEN_CERTIFICATIONS": {
       "TITLE": "{{uid}} - Certificaciónes emitidas",
       "SUMMARY": "Certificaciónes emitidas",
@@ -593,7 +596,8 @@
     "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Esta identidad pronto va a faltar certificación (al menos {{willNeedCertificationCount}}).",
     "REVOCATION_SENT": "Revocación mandada",
     "REVOCATION_SENT_WAITING_PROCESS": "La <b>revocación de esta identidad</b> fue solicitada y está en espera de tratamiento.",
-    "FEATURES_NOT_IMPLEMENTED": "Esta funcionalidad todavía está en proceso de desarrollo.<br/><br/>Porque no <b>contribuir ahora a Cesium</b>, para obtenerla más rápidamente ? ;)"
+    "FEATURES_NOT_IMPLEMENTED": "Esta funcionalidad todavía está en proceso de desarrollo.<br/><br/>Porque no <b>contribuir ahora a Cesium</b>, para obtenerla más rápidamente ? ;)",
+    "EMPTY_TX_HISTORY": "Sin exportación operación"
   },
   "CONFIRM": {
     "POPUP_TITLE": "<b>Confirmación</b>",
diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json
index cbfe59289..1060a66d2 100644
--- a/www/i18n/locale-fr-FR.json
+++ b/www/i18n/locale-fr-FR.json
@@ -114,7 +114,7 @@
     "REPORT_ISSUE": "anomalie",
     "NOT_YOUR_ACCOUNT_QUESTION" : "Vous n'êtes pas propriétaire du compte <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> ?",
     "BTN_CHANGE_ACCOUNT": "Déconnecter ce compte",
-    "CONNECTION_ERROR": "Nœud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifez votre connection Internet, ou changer de nœud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>."
+    "CONNECTION_ERROR": "Nœud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connection Internet, ou changer de nœud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>."
   },
   "SETTINGS": {
     "TITLE": "Paramètres",
@@ -279,6 +279,7 @@
       "TITLE": "Nœud",
       "OWNER": "Appartient à",
       "SHOW_RAW_PEERING": "Voir la fiche de pair",
+      "LAST_BLOCKS": "Derniers blocs",
       "KNOWN_PEERS": "Nœuds connus :",
       "GENERAL_DIVIDER": "Informations générales",
       "ERROR": {
@@ -596,7 +597,7 @@
     "REVOCATION_SENT": "Revocation envoyée",
     "REVOCATION_SENT_WAITING_PROCESS": "La <b>révocation de cette identité</b> a été demandée et est en attente de traitement.",
     "FEATURES_NOT_IMPLEMENTED": "Cette fonctionnalité est encore en cours de développement.<br/><br/>Pourquoi ne pas <b>contribuer à Cesium</b>, pour l'obtenir plus rapidement ? ;)",
-    "EMPTY_TX_HISTORY": "Aucune transaction à exporter"
+    "EMPTY_TX_HISTORY": "Aucune opération à exporter"
   },
   "CONFIRM": {
     "POPUP_TITLE": "<b>Confirmation</b>",
diff --git a/www/i18n/locale-nl-NL.json b/www/i18n/locale-nl-NL.json
index cb39dd35f..d8778b7aa 100644
--- a/www/i18n/locale-nl-NL.json
+++ b/www/i18n/locale-nl-NL.json
@@ -115,19 +115,23 @@
     "BTN_HELP": "Help",
     "REPORT_ISSUE": "Meld een probleem",
     "NOT_YOUR_ACCOUNT_QUESTION" : "Je hoeft niet de rekening <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> in uw bezit?",
-    "BTN_CHANGE_ACCOUNT": "Dit account ontkoppelen"
+    "BTN_CHANGE_ACCOUNT": "Dit account ontkoppelen",
+    "CONNECTION_ERROR": "Node <b>{{server}}</b> onbereikbaar of ongeldig adres.<br/><br/>Controleer de internetverbinding, of schakel knooppunt <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in parameters</a>."
   },
   "SETTINGS": {
     "TITLE": "Instellingen",
     "NETWORK_SETTINGS": "Netwerk",
     "PEER": "Duniter knooppunt adres",
+    "PEER_CHANGED_TEMPORARY": "Adres tijdelijk worden gebruikt",
     "USE_LOCAL_STORAGE": "Lokale opslag inschakelen",
+    "USE_LOCAL_STORAGE_HELP": "Slaat uw instellingen",
     "ENABLE_HELPTIP": "Contextgebonden hulp inschakelen",
     "ENABLE_UI_EFFECTS": "Schakel visuele effecten",
     "HISTORY_SETTINGS": "Mijn rekening",
     "DISPLAY_UD_HISTORY": "Toon geproduceerde dividenden?",
     "AUTHENTICATION_SETTINGS": "Authentificatie",
     "REMEMBER_ME": "Onthoud mij",
+    "REMEMBER_ME_HELP": "Hiermee kunt u blijven altijd aangesloten (niet aanbevolen).",
     "PLUGINS_SETTINGS": "Uitbreidingen",
     "BTN_RESET": "Herstel standaardinstellingen",
     "EXPERT_MODE": "Geavanceerde modus inschakelen",
diff --git a/www/js/controllers/blockchain-controllers.js b/www/js/controllers/blockchain-controllers.js
index 72966d049..78d8df893 100644
--- a/www/js/controllers/blockchain-controllers.js
+++ b/www/js/controllers/blockchain-controllers.js
@@ -29,12 +29,25 @@ angular.module('cesium.blockchain.controllers', ['cesium.services'])
         }
       })
 
-      .state('app.view_currency_block_hash', {
-        url: "/:currency/block/:number/:hash",
+      .state('app.server_blockchain', {
+        url: "/network/peer/:server/blockchain?ssl&tor",
         views: {
           'menuContent': {
-            templateUrl: "templates/blockchain/view_block.html",
-            controller: 'BlockViewCtrl'
+            templateUrl: "templates/blockchain/lookup.html",
+            controller: 'BlockLookupCtrl'
+          }
+        },
+        data: {
+          large: 'app.server_blockchain_lg'
+        }
+      })
+
+      .state('app.server_blockchain_lg', {
+        url: "/network/peer/:server/blockchain/lg?ssl&tor",
+        views: {
+          'menuContent': {
+            templateUrl: "templates/blockchain/lookup_lg.html",
+            controller: 'BlockLookupCtrl'
           }
         }
       })
@@ -57,6 +70,16 @@ angular.module('cesium.blockchain.controllers', ['cesium.services'])
             controller: 'BlockViewCtrl'
           }
         }
+      })
+
+      .state('app.view_server_block_hash', {
+        url: "/network/peer/:server/block/:number/:hash?ssl&tor",
+        views: {
+          'menuContent': {
+            templateUrl: "templates/blockchain/view_block.html",
+            controller: 'BlockViewCtrl'
+          }
+        }
       });
   })
 
@@ -77,6 +100,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
     hasMore: false,
     type: 'last'
   };
+  $scope.node = {};
   $scope.currency = false;
   $scope.entered = false;
   $scope.searchTextId = null;
@@ -96,16 +120,46 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
           $scope.search.type='text';
         }
       }
-      if (state && state.stateParams && state.stateParams.currency) { // Currency parameter
-        $scope.currency = state.stateParams.currency;
+
+      // Load from server if need
+      if (state && state.stateParams && state.stateParams.server) {
+        var useSsl = state.stateParams.ssl == "true";
+        var useTor = state.stateParams.tor == "true";
+
+        var node = {
+          server: state.stateParams.server,
+          host: state.stateParams.server,
+          useSsl: useSsl,
+          useTor: useTor
+        };
+        var serverParts = state.stateParams.server.split(':');
+        if (serverParts.length == 2) {
+          node.host = serverParts[0];
+          node.port = serverParts[1];
+        }
+
+        if (BMA.node.same(node.host, node.port)) {
+          $scope.node = BMA;
+        }
+        else {
+          $scope.node = useTor ?
+              // For TOR, use a web2tor to access the endpoint
+              BMA.instance(node.host + ".to", 443, true/*ssl*/, 600000 /*long timeout*/) :
+              BMA.instance(node.host, node.port, node.useSsl);
+          return $scope.node.blockchain.parameters()
+            .then(function(json) {
+              $scope.currency = json.currency;
+              $scope.enter(); // back to enter()
+            });
+        }
       }
+
       // Load currency if need
       if (!$scope.currency) {
-        csCurrency.get()
+        return csCurrency.get()
           .then(function(currency) {
             $scope.currency = currency ? currency.name : null;
-            $scope.node = !BMA.node.same(currency.node.host, currency.node.port) ?
-              BMA.instance(currency.node.host, currency.node.port) : BMA;
+            $scope.node = currency.node ? currency.node : BMA;
 
             if (!$scope.currency) {
               UIUtils.alert.error('ERROR.GET_CURRENCY_FAILED');
@@ -114,7 +168,6 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
             $scope.enter(); // back to enter()
           })
           .catch(UIUtils.onError('ERROR.GET_CURRENCY_FAILED'));
-        return;
       }
 
       $scope.compactMode = angular.isDefined($scope.compactMode) ? $scope.compactMode : true;
@@ -141,9 +194,10 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
       $scope.startListenBlock();
     }
   };
-  $scope.$on('$ionicView.enter', $scope.enter);
+  //$scope.$on('$ionicView.enter', $scope.enter);
   $scope.$on('$ionicParentView.enter', $scope.enter);
 
+
   /**
    * Leave the view
    * @param e
@@ -156,7 +210,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
       delete $scope.wsBlock;
     }
   };
-  $scope.$on('$ionicView.leave', $scope.leave);
+  //$scope.$on('$ionicView.leave', $scope.leave);
   $scope.$on('$ionicParentView.leave', $scope.leave);
   $scope.$on('$destroy', $scope.leave);
 
@@ -235,6 +289,8 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
       });
   };
 
+  var formatDateShort = $filter('formatDateShort');
+
   $scope.doPrepareResult = function(blocks, offset) {
     offset = angular.isDefined(offset) ? offset : 0;
 
@@ -250,7 +306,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
         // If empty
         if (block.empty) {
           // compute the day
-          var blockDay = $filter('formatDateShort')(block.medianTime);
+          var blockDay = formatDateShort(block.medianTime);
           var notFirstEmpty = (index !== 0) || (offset !== 0);
           var previousNotEmptyOrSameDay = !previousEmptyBlockDay || (previousEmptyBlockDay == blockDay);
           block.compacted = notFirstEmpty && previousNotEmptyOrSameDay;
@@ -429,10 +485,43 @@ function BlockViewController($scope, $ionicPopover, $state, UIUtils, BMA, csCurr
   $scope.enter = function(e, state) {
     if (!$scope.loading) return; // call once
 
-    $scope.currency = state && state.stateParams ? state.stateParams.currency : undefined;
     $scope.number = state && state.stateParams && angular.isDefined(state.stateParams.number) ? state.stateParams.number : 'current';
     $scope.hash = state && state.stateParams && state.stateParams.hash ? state.stateParams.hash : undefined;
 
+    // Load from server if need
+    if (state && state.stateParams && state.stateParams.server) {
+      var useSsl = state.stateParams.ssl == "true";
+      var useTor = state.stateParams.tor == "true";
+
+      var node = {
+        server: state.stateParams.server,
+        host: state.stateParams.server,
+        useSsl: useSsl,
+        useTor: useTor
+      };
+      var serverParts = state.stateParams.server.split(':');
+      if (serverParts.length == 2) {
+        node.host = serverParts[0];
+        node.port = serverParts[1];
+      }
+
+      if (BMA.node.same(node.host, node.port)) {
+        $scope.node = BMA;
+      }
+      else {
+        $scope.node = useTor ?
+          // For TOR, use a web2tor to access the endpoint
+          BMA.instance(node.host + ".to", 443, true/*ssl*/, 600000 /*long timeout*/) :
+          BMA.instance(node.host, node.port, node.useSsl);
+        return $scope.node.blockchain.parameters()
+          .then(function(json) {
+            $scope.currency = json.currency;
+            $scope.enter(); // back to enter()
+          });
+      }
+    }
+
+
     if (!$scope.currency) {
       csCurrency.get()
         .then(function (currency) {
@@ -445,7 +534,6 @@ function BlockViewController($scope, $ionicPopover, $state, UIUtils, BMA, csCurr
         .catch(UIUtils.onError('ERROR.GET_CURRENCY_FAILED'));
     }
     else {
-      $scope.node = BMA;
       $scope.load();
     }
   };
diff --git a/www/plugins/graph/templates/network/view_peer_extend.html b/www/plugins/graph/templates/network/view_peer_extend.html
index a2856373c..f4f62451b 100644
--- a/www/plugins/graph/templates/network/view_peer_extend.html
+++ b/www/plugins/graph/templates/network/view_peer_extend.html
@@ -1,7 +1,7 @@
 <!-- Buttons section -->
 <ng-if ng-if="enable && extensionPoint === 'general'">
 
-  <a class="item item-icon-left item-text-wrap ink"
+  <a class="item item-icon-left item-icon-right item-text-wrap ink"
     ui-sref="app.view_peer_stats({pubkey: node.pubkey})">
     <i class="icon ion-stats-bars"></i>
     <span translate>GRAPH.PEER.VIEW.BLOCK_COUNT_LABEL</span>
@@ -11,6 +11,7 @@
       {{!blockCount ? 'GRAPH.PEER.VIEW.NO_BLOCK' : 'GRAPH.PEER.VIEW.BLOCK_COUNT' | translate:{count: blockCount} }}
     </span>
     <ion-spinner class="badge" icon="android" ng-if="loading"></ion-spinner>
+    <i class="gray icon ion-ios-arrow-right"></i>
   </a>
 </ng-if>
 
diff --git a/www/templates/blockchain/list_blocks_lg.html b/www/templates/blockchain/list_blocks_lg.html
index d8d16d735..9fa8b9fcb 100644
--- a/www/templates/blockchain/list_blocks_lg.html
+++ b/www/templates/blockchain/list_blocks_lg.html
@@ -17,7 +17,7 @@
     <ion-spinner icon="android"></ion-spinner>
   </div>
 
-  <ion-list class="animate-ripple padding padding-xs">
+  <ion-list class="padding padding-xs list-blocks" ng-class="::motion.ionListClass">
     <div class="padding gray" ng-if="!search.loading && !search.results.length" translate>
       BLOCKCHAIN.LOOKUP.NO_BLOCK
     </div>
diff --git a/www/templates/network/view_peer.html b/www/templates/network/view_peer.html
index 677ebd8af..bb75dabf2 100644
--- a/www/templates/network/view_peer.html
+++ b/www/templates/network/view_peer.html
@@ -66,14 +66,22 @@
           <h4 class="dark text-left">{{node.pubkey}}</h4>
         </ion-item>
 
-        <a class="item item-icon-left item-text-wrap ink"
-                  target="_blank"
-                  ng-href="{{(node.useSsl ? 'https://' : 'http://') + node.server}}/blockchain/current">
+        <a class="item item-icon-left item-icon-right item-text-wrap ink"
+           ui-sref="app.view_server_block_hash({server: node.server, ssl: node.useSsl, tor: node.useTor, number: current.number, hash: current.hash})">
           <i class="icon ion-cube"></i>
           <span translate>BLOCKCHAIN.VIEW.TITLE_CURRENT</span>
           <div class="badge badge-calm" ng-if="!loading">
             {{current.number|formatInteger}}
           </div>
+          <i class="gray icon ion-ios-arrow-right"></i>
+        </a>
+
+        <a class="item item-icon-left item-icon-right item-text-wrap ink"
+           ui-sref="app.server_blockchain({server: node.server, ssl: node.useSsl, tor: node.useTor})">
+          <i class="icon ion-cube" style="font-size: 25px;"></i>
+          <i class="icon-secondary ion-clock" style="font-size: 18px; left: 33px; top: -12px;"></i>
+          <span translate>PEER.VIEW.LAST_BLOCKS</span>
+          <i class="gray icon ion-ios-arrow-right"></i>
         </a>
 
         <!-- Allow extension here -->
-- 
GitLab