From 8b692c7c29d52c7bf2bef52d87ac2572862a2d43 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Fri, 2 Jun 2017 15:43:38 +0200
Subject: [PATCH 01/48] change specialize node to module

---
 index.js                | 14 +++++++-------
 lib/updateCache.js      |  1 +
 package.json            | 36 +++++++++++++++++++-----------------
 routes/pubkeyBalance.js |  2 +-
 run.js                  |  1 +
 5 files changed, 29 insertions(+), 25 deletions(-)
 create mode 100644 run.js

diff --git a/index.js b/index.js
index 9d997fa..2a79d76 100755
--- a/index.js
+++ b/index.js
@@ -9,7 +9,7 @@ const duniter = require('duniter');
  ***************************************/
 
 // Default Duniter node's database
-const DEFAULT_DUNITER_DATA_FOLDER = 'currency-monit-dev';
+//const DEFAULT_DUNITER_DATA_FOLDER = 'currency-monit-dev';
 
 // host on which UI is available
 const DEFAULT_HOST = 'localhost';
@@ -21,10 +21,10 @@ const DEFAULT_PORT = 10500;
  * SPECIALIZATION
  ***************************************/
 
-const stack = duniter.statics.autoStack([{
+/*const stack = duniter.statics.autoStack([{
   name: 'currency-monit',
-  required: {
-
+  required: {*/
+module.exports = {
     duniter: {
 
       cli: [{
@@ -52,9 +52,9 @@ const stack = duniter.statics.autoStack([{
       }]
     }
   }
-}]);
+//}]);
 
-co(function*() {
+/*co(function*() {
   if (!process.argv.includes('--mdb')) {
     // We use the default database
     process.argv.push('--mdb');
@@ -64,4 +64,4 @@ co(function*() {
   yield stack.executeStack(process.argv);
   // End
   process.exit();
-});
+});*/
diff --git a/lib/updateCache.js b/lib/updateCache.js
index 15ccc8e..227d087 100755
--- a/lib/updateCache.js
+++ b/lib/updateCache.js
@@ -190,6 +190,7 @@ module.exports = (req, res, next) => co(function *() {
 	  let inputsSum = 0;
 	  for (let i=0;i<transactions[t].inputs.length;i++)
 	  {
+	    console.log("(b, t, i) = %s, %s, %s", b, t, i);
 	    let input = transactions[t].inputs[i].split(":");
 	    inputsSum += (parseInt(input[0])*Math.pow(10, parseInt(input[1])));
 	  }
diff --git a/package.json b/package.json
index 770ef0a..86ae25e 100755
--- a/package.json
+++ b/package.json
@@ -1,33 +1,35 @@
 {
-  "name": "specialnodemembers",
-  "version": "1.1.1",
-  "description": "",
+  "name": "duniter-currency-monit",
+  "version": "0.3.2",
   "main": "index.js",
-  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1",
-    "brunch": "cd ui node && npm install && npm run-script brunch",
-    "brunch-build": "cd ui node && npm run-script brunch-build",
-    "brunch-w": "cd ui node && npm run-script brunch-w"
-  },
+  "license": "AGPLv3",
   "dependencies": {
+    "adm-zip": "^0.4.7",
     "body-parser": "1.15.1",
-    "co": "4.6.0",
+    "co": "^4.6.0",
     "commander": "2.9.0",
-    "duniter": "^1.2.3",
-    "duniter-bma": "1.1.2",
-    "duniter-crawler": "1.1.4",
-    "duniter-keypair": "1.1.3",
-    "duniter-prover": "1.1.2",
     "event-stream": "3.3.4",
     "express": "4.13.4",
+    "fs-extra": "^3.0.1",
     "http": "0.0.0",
     "morgan": "1.7.0",
     "node-pre-gyp": "^0.6.34",
     "q": "1.5.0",
+    "request": "^2.81.0",
     "request-promise": "4.2.0",
+    "rimraf": "^2.6.1",
+    "tmp": "^0.0.31",
     "underscore": "1.8.3",
     "ws": "1.1.1"
   },
-  "author": "",
-  "license": "GPLv3"
+  "devDependencies": {
+    "duniter": "^1.3.0",
+    "duniter-keypair": "^1.3.x",
+    "duniter-bma": "1.3.x",
+    "duniter-crawler": "1.3.x",
+    "duniter-prover": "1.3.x"
+  },
+  "peerDependencies": {
+    "duniter": "^1.3.0"
+  }
 }
diff --git a/routes/pubkeyBalance.js b/routes/pubkeyBalance.js
index 479a7ad..adbea1d 100755
--- a/routes/pubkeyBalance.js
+++ b/routes/pubkeyBalance.js
@@ -468,7 +468,7 @@ module.exports = (req, res, next) => co(function *() {
 	  form: `${LANG["BEGIN"]} #<input type="number" name="begin" value="${cache.beginBlock[0].number}" size="7" style="width:60px;" min="0"  ${(mode == "balanceWithOthers") ? 'disabled':''}>
 	     - ${LANG["END"]} #<input type="number" name="end" value="${cache.endBlock[0].number}" size="7" style="width:60px;" min="1"  ${(mode == "balanceWithOthers") ? 'disabled':''}>
 	     - ${LANG["PUBKEY"]} : <input type="text" name="pubkey1" value="${pubkey1}" size="44">
-	    <select name="mode">
+	    <select name="mode" disabled>
 	      <option name="mode" value ="selfBalance">${LANG["SELECT_MODE1"]}
 	      <option name="mode" value ="balanceWithOthers" ${mode == 'balanceWithOthers' ? 'selected' : ''}>${LANG["SELECT_MODE2"]}
 	    </select>
diff --git a/run.js b/run.js
new file mode 100644
index 0000000..3f097ba
--- /dev/null
+++ b/run.js
@@ -0,0 +1 @@
+require('duniter').statics.quickRun('./index.js')
\ No newline at end of file
-- 
GitLab


From dd3e276726bad76b2806ca51e6895be00540cfba Mon Sep 17 00:00:00 2001
From: root <root@ifee3>
Date: Fri, 2 Jun 2017 16:12:13 +0200
Subject: [PATCH 02/48] suppr pages membersCount and pubkeyBalance

---
 routes/index.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/routes/index.js b/routes/index.js
index 0e7ae46..044b578 100755
--- a/routes/index.js
+++ b/routes/index.js
@@ -75,11 +75,11 @@ app.get('/members', /*require('../lib/updateCache.js'),*/ require('./members.js'
 /***************************************
 * Évolution du nombre de membres
 ***************************************/
-app.get('/membersCount', require('../lib/updateCache.js'), require('./membersCount.js'), (req, res)=> res.render('Chart.html', {
+/*app.get('/membersCount', require('../lib/updateCache.js'), require('./membersCount.js'), (req, res)=> res.render('Chart.html', {
             MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`./lg/membersCount_${req.query.lg||'fr'}.txt`)
          })
- )
+ )*/
 
 /***************************************
 * Lister les block en graph
@@ -103,10 +103,10 @@ app.get('/monetaryMass', require('./monetaryMass.js'), (req, res)=> res.render('
 /***************************************
 * Évolution de la masse monétaire totale
 ***************************************/
-app.get('/pubkeyBalance', require('../lib/updateCache.js'), require('./pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
+/*app.get('/pubkeyBalance', require('../lib/updateCache.js'), require('./pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
             MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`./lg/pubkeyBalance_${req.query.lg||'fr'}.txt`)
          })
- )
+ )*/
 
 module.exports = app
\ No newline at end of file
-- 
GitLab


From 2382f4430043cd2113867887d781d473cf3d7621 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 7 Jun 2017 14:01:07 +0200
Subject: [PATCH 03/48] change all relativ patch to absolutes patch

---
 index.js                |  2 +-
 lib/main.js             | 12 ++++------
 lib/webserver.js        | 12 +++++-----
 package.json            |  6 ++---
 routes/blockCount.js    |  4 ++--
 routes/index.js         | 50 ++++++++++++++++++++---------------------
 routes/members.js       |  2 +-
 routes/membersCount.js  |  4 ++--
 routes/monetaryMass.js  |  2 +-
 routes/pubkeyBalance.js |  6 ++---
 routes/willMembers.js   |  2 +-
 views/Chart.html        |  4 ++--
 views/about.html        |  4 ++--
 views/members.html      |  4 ++--
 views/willMembers.html  |  4 ++--
 15 files changed, 57 insertions(+), 61 deletions(-)

diff --git a/index.js b/index.js
index 2a79d76..7f4fd3b 100755
--- a/index.js
+++ b/index.js
@@ -28,7 +28,7 @@ module.exports = {
     duniter: {
 
       cli: [{
-        name: 'currency-monit [host] [port] [data-folder]',
+        name: 'currency-monit [host] [port]',
         desc: 'Starts specialized node currency-monit',
 
         // Disables Duniter node's logs
diff --git a/lib/main.js b/lib/main.js
index 24701e3..63e61b0 100755
--- a/lib/main.js
+++ b/lib/main.js
@@ -1,8 +1,8 @@
 "use strict";
 
 const co = require('co');
-const webserver = require('./webserver.js');
-const duniter = require('./duniter.js');
+const webserver = require(__dirname + '/webserver.js');
+const duniter = require(__dirname + '/duniter.js');
 
 /****************************
  * Main algorithm
@@ -18,12 +18,8 @@ module.exports = (duniterServer, host, port) => co(function *() {
   const idtyWindow = tabParameters[8];
   const sigQty = tabParameters[7];
   const stepMax = tabParameters[12];
-  console.log("msValidity = %s", msValidity);
-  console.log("sigValidity = %s", sigValidity);
-  console.log("sigWindow = %s", sigWindow);
-  console.log("idtyWindow = %s", idtyWindow);
-  console.log("sigQty = %s", sigQty);
-  console.log("stepMax = %s", stepMax);
+  console.log("currency-monit started");
+  console.log("__dirname = %s", __dirname);
   
   // Define cache
   var cache = {
diff --git a/lib/webserver.js b/lib/webserver.js
index 33bed87..04a9de6 100755
--- a/lib/webserver.js
+++ b/lib/webserver.js
@@ -8,17 +8,17 @@ const co = require('co');
 const http = require('http');
 const morgan = require('morgan');
 const express = require('express');
-const routes = require('../routes');
 const bodyParser = require('body-parser');
 
-const tpl = require('./tplit.js');
+const routes = require(__dirname + '/../routes');
+const tpl = require(__dirname + '/tplit.js');
 
 module.exports = (host, port, duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache) => {
   
   var app = express();
   
   // Redirect stdout to access.log
-  const logFile = fs.createWriteStream('./access.log', { flags: 'a' });
+  const logFile = fs.createWriteStream(__dirname + '/access.log', { flags: 'a' });
   console.log = function () {
     logFile.write(util.format.apply(null, arguments) + '\n');
   }
@@ -34,7 +34,7 @@ module.exports = (host, port, duniterServer, sigValidity, msValidity, sigWindow,
   app.use(bodyParser.urlencoded({ extended: true }));
   
   app.engine('html', tpl )
-  app.set('views', './views') // specify the views directory
+  app.set('views', __dirname + '/../views') // specify the views directory
   app.set('view engine', 'html') // register the template engine
   
   app.locals.duniterServer = duniterServer
@@ -46,8 +46,8 @@ module.exports = (host, port, duniterServer, sigValidity, msValidity, sigWindow,
   app.locals.stepMax = stepMax
   app.locals.cache = cache
   
-  app.locals.HTML_HEAD = fs.readFileSync('./views/HEAD.html', 'utf-8')
-  app.locals.HTML_TOR_HEAD = fs.readFileSync('./views/TOR_HEAD.html', 'utf-8')
+  app.locals.HTML_HEAD = fs.readFileSync(__dirname + '/../views/HEAD.html', 'utf-8')
+  app.locals.HTML_TOR_HEAD = fs.readFileSync(__dirname + '/../views/TOR_HEAD.html', 'utf-8')
   
   app.use( routes )
   
diff --git a/package.json b/package.json
index 86ae25e..18b0386 100755
--- a/package.json
+++ b/package.json
@@ -23,13 +23,13 @@
     "ws": "1.1.1"
   },
   "devDependencies": {
-    "duniter": "^1.3.0",
-    "duniter-keypair": "^1.3.x",
+    "duniter": "1.3.2",
+    "duniter-keypair": "1.3.x",
     "duniter-bma": "1.3.x",
     "duniter-crawler": "1.3.x",
     "duniter-prover": "1.3.x"
   },
   "peerDependencies": {
-    "duniter": "^1.3.0"
+    "duniter": "1.3.2"
   }
 }
diff --git a/routes/blockCount.js b/routes/blockCount.js
index dac5ca7..20f6bfe 100755
--- a/routes/blockCount.js
+++ b/routes/blockCount.js
@@ -1,8 +1,8 @@
 "use strict";
 
 const co = require('co')
-const timestampToDatetime = require('../lib/timestampToDatetime')
-const colorScale = require('../lib/colorScale')
+const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
+const colorScale = require(__dirname + '/../lib/colorScale')
 
 // Garder l'index des blocs en mémoire vive
 var blockchain = [];
diff --git a/routes/index.js b/routes/index.js
index 044b578..0e94d27 100755
--- a/routes/index.js
+++ b/routes/index.js
@@ -1,6 +1,6 @@
 const fs = require('fs')
 const express = require('express')
-const getLang = require('../lib/getLang')
+const getLang = require(__dirname + '/../lib/getLang')
 
 var app = express.Router()
 
@@ -27,7 +27,7 @@ Par exemple, home et about n'ont pas besoin de controleur
 ***************************************/
 app.get('/', (req, res)=> res.render('about.html', {
             host: req.headers.host.toString(),
-	    MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`)
+	    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`)
          })
  )
 
@@ -36,7 +36,7 @@ app.get('/', (req, res)=> res.render('about.html', {
 ***************************************/
 app.get('/about', (req, res)=> res.render('about.html', {
 	    host: req.headers.host.toString(),
-            MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`)
+            MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`)
          })
  )
 
@@ -44,68 +44,68 @@ app.get('/about', (req, res)=> res.render('about.html', {
 * Lister les futurs membres
 ***************************************/
 app.get('/willMembers', 
-  require('./willMembers.js'), // the route controler
+  require(__dirname + '/willMembers.js'), // the route controler
   (req, res)=> // Send html page
       res.status(200) // 200 n'est pas obligatoire, si on renvoie une réponse
          .render('willMembers.html', {
-	    MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
-            LANG: getLang(`./lg/willMembers_${req.query.lg||'fr'}.txt`)
+	    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
+            LANG: getLang(`${__dirname}/../lg/willMembers_${req.query.lg||'fr'}.txt`)
          })
 )
 
 /***************************************
 * Lister les membres
 ***************************************/
-app.get('/members', /*require('../lib/updateCache.js'),*/ require('./members.js'),
+app.get('/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/members.js'),
   (req, res)=> res.render('members.html', {
-		    MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
-                    LANG: getLang(`./lg/members_${req.query.lg||'fr'}.txt`)
+		    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
+                    LANG: getLang(`${__dirname}/../lg/members_${req.query.lg||'fr'}.txt`)
                   })
 )
 
 /***************************************
 * Lister les anciens membres
 ***************************************/
-/*app.get('/wasMembers', require('./wasMembers.js'), (req, res)=> res.render('wasMembers.html', {
-            MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
-            LANG: getLang(`./lg/wasMembers_${lg}.txt`)
+/*app.get('/wasMembers', require(__dirname + '/wasMembers.js'), (req, res)=> res.render('wasMembers.html', {
+            MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
+            LANG: getLang(`${__dirname}/../lg/wasMembers_${lg}.txt`)
          })
  )*/
 
 /***************************************
 * Évolution du nombre de membres
 ***************************************/
-/*app.get('/membersCount', require('../lib/updateCache.js'), require('./membersCount.js'), (req, res)=> res.render('Chart.html', {
-            MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
-            LANG: getLang(`./lg/membersCount_${req.query.lg||'fr'}.txt`)
+/*app.get('/membersCount', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/membersCount.js'), (req, res)=> res.render('Chart.html', {
+            MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
+            LANG: getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`)
          })
  )*/
 
 /***************************************
 * Lister les block en graph
 ***************************************/
-app.get('/blockCount', /*require('../lib/updateCache.js'),*/ require('./blockCount.js'), (req, res)=> res.render('Chart.html', {
-            MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
-            LANG: getLang(`./lg/blockCount_${req.query.lg||'fr'}.txt`)
+app.get('/blockCount', /*require('${__dirname}/../lib/updateCache.js'),*/ require(__dirname + '/blockCount.js'), (req, res)=> res.render('Chart.html', {
+            MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
+            LANG: getLang(`${__dirname}/../lg/blockCount_${req.query.lg||'fr'}.txt`)
          })
  )
 
 /***************************************
 * Évolution de la masse monétaire totale
 ***************************************/
-app.get('/monetaryMass', require('./monetaryMass.js'), (req, res)=> res.render('Chart.html', {
-            MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
-            LANG: getLang(`./lg/monetaryMass_${req.query.lg||'fr'}.txt`)
+app.get('/monetaryMass', require(__dirname + '/monetaryMass.js'), (req, res)=> res.render('Chart.html', {
+            MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
+            LANG: getLang(`${__dirname}/../lg/monetaryMass_${req.query.lg||'fr'}.txt`)
          })
  )
 
 
 /***************************************
-* Évolution de la masse monétaire totale
+* Solde d'une clé
 ***************************************/
-/*app.get('/pubkeyBalance', require('../lib/updateCache.js'), require('./pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
-            MENU_LANG: getLang(`./lg/menu_${req.query.lg||'fr'}.txt`),
-            LANG: getLang(`./lg/pubkeyBalance_${req.query.lg||'fr'}.txt`)
+/*app.get('/pubkeyBalance', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
+            MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
+            LANG: getLang(`${__dirname}/../lg/pubkeyBalance_${req.query.lg||'fr'}.txt`)
          })
  )*/
 
diff --git a/routes/members.js b/routes/members.js
index e648b17..c37916a 100755
--- a/routes/members.js
+++ b/routes/members.js
@@ -1,7 +1,7 @@
 "use strict";
 
 const co = require('co')
-const timestampToDatetime = require('../lib/timestampToDatetime')
+const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
 module.exports = (req, res, next) => co(function *() {
   
diff --git a/routes/membersCount.js b/routes/membersCount.js
index ae90b0b..6d76638 100755
--- a/routes/membersCount.js
+++ b/routes/membersCount.js
@@ -1,8 +1,8 @@
 "use strict";
 
 const co = require('co')
-const timestampToDatetime = require('../lib/timestampToDatetime')
-const getLang = require('../lib/getLang')
+const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
+const getLang = require(__dirname + '/../lib/getLang')
 
 const STEP_COUNT_MAX = 150;
 
diff --git a/routes/monetaryMass.js b/routes/monetaryMass.js
index 2ab69e5..0d21b35 100755
--- a/routes/monetaryMass.js
+++ b/routes/monetaryMass.js
@@ -1,7 +1,7 @@
 "use strict";
 
 const co = require('co')
-const timestampToDatetime = require('../lib/timestampToDatetime')
+const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
 module.exports = (req, res, next) => co(function *() {
   
diff --git a/routes/pubkeyBalance.js b/routes/pubkeyBalance.js
index adbea1d..2657e01 100755
--- a/routes/pubkeyBalance.js
+++ b/routes/pubkeyBalance.js
@@ -1,9 +1,9 @@
 "use strict";
 
 const co = require('co')
-const timestampToDatetime = require('../lib/timestampToDatetime')
-const colorScale = require('../lib/colorScale')
-const getLang = require('../lib/getLang')
+const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
+const colorScale = require(__dirname + '/../lib/colorScale')
+const getLang = require(__dirname + '/../lib/getLang')
 
 const STEP_COUNT_LIMIT=150;
 
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 01cbc44..45f93d6 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -2,7 +2,7 @@
 
 const co = require('co')
 const crypto = require('crypto');
-const timestampToDatetime = require('../lib/timestampToDatetime')
+const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
 // Préserver les résultats en cache
 
diff --git a/views/Chart.html b/views/Chart.html
index 4214ce4..9336a48 100755
--- a/views/Chart.html
+++ b/views/Chart.html
@@ -6,10 +6,10 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+    <!-- <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
     <td><a href="blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td>
+    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
     <td><a href="about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
diff --git a/views/about.html b/views/about.html
index 74c7c6b..cf027bc 100755
--- a/views/about.html
+++ b/views/about.html
@@ -5,10 +5,10 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+    <!-- <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
     <td><a href="blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td>
+    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
     <td><a href="about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
diff --git a/views/members.html b/views/members.html
index e3f9375..dc57e5c 100755
--- a/views/members.html
+++ b/views/members.html
@@ -5,10 +5,10 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+    <!-- <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
     <td><a href="blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td>
+    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
     <td><a href="about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
diff --git a/views/willMembers.html b/views/willMembers.html
index 5b7c20d..557708f 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -5,10 +5,10 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+    <!-- <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
     <td><a href="blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td>
+    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
     <td><a href="about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
-- 
GitLab


From f76476ad672885cec027e250272e75082de547f8 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 7 Jun 2017 14:15:37 +0200
Subject: [PATCH 04/48] remove call to duniter module

---
 index.js       | 2 +-
 lib/duniter.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
 mode change 100644 => 100755 lib/duniter.js

diff --git a/index.js b/index.js
index 7f4fd3b..bea9f03 100755
--- a/index.js
+++ b/index.js
@@ -2,7 +2,7 @@
 
 const co = require('co');
 const main = require('./lib/main.js');
-const duniter = require('duniter');
+//const duniter = require('duniter');
 
 /****************************************
  * TECHNICAL CONFIGURATION
diff --git a/lib/duniter.js b/lib/duniter.js
old mode 100644
new mode 100755
index 4f9bd02..4213ed6
--- a/lib/duniter.js
+++ b/lib/duniter.js
@@ -1,7 +1,7 @@
 "use strict";
 
 const co = require('co');
-const duniter = require('duniter');
+//const duniter = require('duniter');
 
 module.exports = (dataFolder, httpLogs) => co(function *() {
 
-- 
GitLab


From 120041fc2dae6e0ffe5ef0f275fb055957e753b0 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 7 Jun 2017 14:36:42 +0200
Subject: [PATCH 05/48] add ui icon

---
 index.js          | 21 ++++++++++++++++++++-
 injection/menu.js | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100755 injection/menu.js

diff --git a/index.js b/index.js
index bea9f03..5f12f9d 100755
--- a/index.js
+++ b/index.js
@@ -1,7 +1,7 @@
 "use strict";
 
 const co = require('co');
-const main = require('./lib/main.js');
+const main = require(__dirname + '/lib/main.js');
 //const duniter = require('duniter');
 
 /****************************************
@@ -50,6 +50,25 @@ module.exports = {
           yield new Promise(() => null);
         })
       }]
+    },
+    duniterUI: {
+      inject: {
+	menu: fs.readFileSync(path.join(__dirname, 'injection/menu.js'), 'utf8')
+      },
+      route: (app, server, conf, program, params) => {
+	// currency-monit parameters
+        const SERVER_HOST = params[0] || DEFAULT_HOST;
+        const SERVER_PORT = parseInt(params[1]) || DEFAULT_PORT;
+
+        // IMPORTANT: release Duniter services from "sleep" mode
+        yield startServices();
+
+        // Main Loop
+        yield main(server, SERVER_HOST, SERVER_PORT);
+
+        // Wait forever, this is a permanent program
+        yield new Promise(() => null);
+      }
     }
   }
 //}]);
diff --git a/injection/menu.js b/injection/menu.js
new file mode 100755
index 0000000..aa37329
--- /dev/null
+++ b/injection/menu.js
@@ -0,0 +1,36 @@
+(function inject(window) {
+
+  "use strict";
+
+  var openNewTab = window.openNewTab
+  var mainWindow = window.mainWindow
+
+  window.uiModules['duniter-currency-monit'] = {
+    menuIconClass: 'fa-signal',
+    menuLabel: 'Ğune Monit',
+    menuOpen: openCurrencyMonitModule
+  }
+
+  function openCurrencyMonitModule() {
+
+    var currencyMonitModuleHeight = parseInt(localStorage.getItem('currency_monit_module_height')) || 1000;
+    var currencyMonitModuleWidth = parseInt(localStorage.getItem('currency_monit_module_width')) || 1400;
+
+    //openNewTab (window.location.origin + '/rml9-web-module/index.html', {
+    openNewTab ('localhost:10500', {
+      position: 'center',
+      height: currencyMonitModuleHeight,
+      width: currencyMonitModuleWidth,
+      show: false
+    }, function(win) {
+      win.show();
+      // Remember the window size
+      win.on('closed', function() {
+        localStorage.setItem('currency_monit_module_height', win.window.innerHeight - 8); // Seems to always have 8 pixels more
+        localStorage.setItem('currency_monit_module_width', win.window.innerWidth - 16); // Seems to always have 16 pixels more
+        mainWindow.focus();
+      });
+    });
+  }
+
+})(window);
-- 
GitLab


From b70b1273ae36e46c3678165e1d0e15c2eb835cec Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 7 Jun 2017 14:59:13 +0200
Subject: [PATCH 06/48] change patch / to /currency-monit

---
 index.js               |  9 ++++-----
 injection/menu.js      |  2 +-
 routes/index.js        | 18 +++++++++---------
 views/Chart.html       | 14 +++++++-------
 views/about.html       | 14 +++++++-------
 views/members.html     | 14 +++++++-------
 views/willMembers.html | 14 +++++++-------
 7 files changed, 42 insertions(+), 43 deletions(-)

diff --git a/index.js b/index.js
index 5f12f9d..f56a088 100755
--- a/index.js
+++ b/index.js
@@ -1,6 +1,8 @@
 "use strict";
 
 const co = require('co');
+const fs = require('fs')
+const path = require('path')
 const main = require(__dirname + '/lib/main.js');
 //const duniter = require('duniter');
 
@@ -60,14 +62,11 @@ module.exports = {
         const SERVER_HOST = params[0] || DEFAULT_HOST;
         const SERVER_PORT = parseInt(params[1]) || DEFAULT_PORT;
 
-        // IMPORTANT: release Duniter services from "sleep" mode
-        yield startServices();
-
         // Main Loop
-        yield main(server, SERVER_HOST, SERVER_PORT);
+        main(server, SERVER_HOST, SERVER_PORT);
 
         // Wait forever, this is a permanent program
-        yield new Promise(() => null);
+        new Promise(() => null);
       }
     }
   }
diff --git a/injection/menu.js b/injection/menu.js
index aa37329..07488cc 100755
--- a/injection/menu.js
+++ b/injection/menu.js
@@ -17,7 +17,7 @@
     var currencyMonitModuleWidth = parseInt(localStorage.getItem('currency_monit_module_width')) || 1400;
 
     //openNewTab (window.location.origin + '/rml9-web-module/index.html', {
-    openNewTab ('localhost:10500', {
+    openNewTab ((window.location.origin + '/currency-monit/', {
       position: 'center',
       height: currencyMonitModuleHeight,
       width: currencyMonitModuleWidth,
diff --git a/routes/index.js b/routes/index.js
index 0e94d27..9d2db0d 100755
--- a/routes/index.js
+++ b/routes/index.js
@@ -25,7 +25,7 @@ Par exemple, home et about n'ont pas besoin de controleur
 /***************************************
 * Home Page
 ***************************************/
-app.get('/', (req, res)=> res.render('about.html', {
+app.get('/currency-monit/', (req, res)=> res.render('about.html', {
             host: req.headers.host.toString(),
 	    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`)
          })
@@ -34,7 +34,7 @@ app.get('/', (req, res)=> res.render('about.html', {
 /***************************************
 * About Page
 ***************************************/
-app.get('/about', (req, res)=> res.render('about.html', {
+app.get('/currency-monit/about', (req, res)=> res.render('about.html', {
 	    host: req.headers.host.toString(),
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`)
          })
@@ -43,7 +43,7 @@ app.get('/about', (req, res)=> res.render('about.html', {
 /***************************************
 * Lister les futurs membres
 ***************************************/
-app.get('/willMembers', 
+app.get('/currency-monit/willMembers', 
   require(__dirname + '/willMembers.js'), // the route controler
   (req, res)=> // Send html page
       res.status(200) // 200 n'est pas obligatoire, si on renvoie une réponse
@@ -56,7 +56,7 @@ app.get('/willMembers',
 /***************************************
 * Lister les membres
 ***************************************/
-app.get('/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/members.js'),
+app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/members.js'),
   (req, res)=> res.render('members.html', {
 		    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
                     LANG: getLang(`${__dirname}/../lg/members_${req.query.lg||'fr'}.txt`)
@@ -66,7 +66,7 @@ app.get('/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/
 /***************************************
 * Lister les anciens membres
 ***************************************/
-/*app.get('/wasMembers', require(__dirname + '/wasMembers.js'), (req, res)=> res.render('wasMembers.html', {
+/*app.get('/currency-monit/wasMembers', require(__dirname + '/wasMembers.js'), (req, res)=> res.render('wasMembers.html', {
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/wasMembers_${lg}.txt`)
          })
@@ -75,7 +75,7 @@ app.get('/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/
 /***************************************
 * Évolution du nombre de membres
 ***************************************/
-/*app.get('/membersCount', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/membersCount.js'), (req, res)=> res.render('Chart.html', {
+/*app.get('/currency-monit/membersCount', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/membersCount.js'), (req, res)=> res.render('Chart.html', {
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`)
          })
@@ -84,7 +84,7 @@ app.get('/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/
 /***************************************
 * Lister les block en graph
 ***************************************/
-app.get('/blockCount', /*require('${__dirname}/../lib/updateCache.js'),*/ require(__dirname + '/blockCount.js'), (req, res)=> res.render('Chart.html', {
+app.get('/currency-monit/blockCount', /*require('${__dirname}/../lib/updateCache.js'),*/ require(__dirname + '/blockCount.js'), (req, res)=> res.render('Chart.html', {
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/blockCount_${req.query.lg||'fr'}.txt`)
          })
@@ -93,7 +93,7 @@ app.get('/blockCount', /*require('${__dirname}/../lib/updateCache.js'),*/ requir
 /***************************************
 * Évolution de la masse monétaire totale
 ***************************************/
-app.get('/monetaryMass', require(__dirname + '/monetaryMass.js'), (req, res)=> res.render('Chart.html', {
+app.get('/currency-monit/monetaryMass', require(__dirname + '/monetaryMass.js'), (req, res)=> res.render('Chart.html', {
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/monetaryMass_${req.query.lg||'fr'}.txt`)
          })
@@ -103,7 +103,7 @@ app.get('/monetaryMass', require(__dirname + '/monetaryMass.js'), (req, res)=> r
 /***************************************
 * Solde d'une clé
 ***************************************/
-/*app.get('/pubkeyBalance', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
+/*app.get('/currency-monit/pubkeyBalance', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/pubkeyBalance_${req.query.lg||'fr'}.txt`)
          })
diff --git a/views/Chart.html b/views/Chart.html
index 9336a48..1e505f7 100755
--- a/views/Chart.html
+++ b/views/Chart.html
@@ -4,13 +4,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <script src=${(host.substr(host.length-6,6) == '.onion') ? "http://722iprlhm7pw4mx7.onion/js/Chart.min.js":"https://librelois.fr/js/Chart.min.js"}></script>
 <table align="center" width="100%">
   <tr>
-    <td><a href="willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
diff --git a/views/about.html b/views/about.html
index cf027bc..58af527 100755
--- a/views/about.html
+++ b/views/about.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
diff --git a/views/members.html b/views/members.html
index dc57e5c..4843864 100755
--- a/views/members.html
+++ b/views/members.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
diff --git a/views/willMembers.html b/views/willMembers.html
index 557708f..35231bf 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
-- 
GitLab


From b649df2f68d230c2bcd814ced220e1db505a98f1 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 7 Jun 2017 20:10:23 +0200
Subject: [PATCH 07/48] change injection icon

---
 index.js          | 7 ++++---
 injection/menu.js | 2 +-
 lib/main.js       | 3 +--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/index.js b/index.js
index f56a088..74d7dde 100755
--- a/index.js
+++ b/index.js
@@ -1,8 +1,8 @@
 "use strict";
 
 const co = require('co');
-const fs = require('fs')
-const path = require('path')
+const fs = require('fs');
+const path = require('path');
 const main = require(__dirname + '/lib/main.js');
 //const duniter = require('duniter');
 
@@ -31,7 +31,7 @@ module.exports = {
 
       cli: [{
         name: 'currency-monit [host] [port]',
-        desc: 'Starts specialized node currency-monit',
+        desc: 'Start duniter with module currency-monit',
 
         // Disables Duniter node's logs
         logs: false,
@@ -57,6 +57,7 @@ module.exports = {
       inject: {
 	menu: fs.readFileSync(path.join(__dirname, 'injection/menu.js'), 'utf8')
       },
+      
       route: (app, server, conf, program, params) => {
 	// currency-monit parameters
         const SERVER_HOST = params[0] || DEFAULT_HOST;
diff --git a/injection/menu.js b/injection/menu.js
index 07488cc..7508bfa 100755
--- a/injection/menu.js
+++ b/injection/menu.js
@@ -17,7 +17,7 @@
     var currencyMonitModuleWidth = parseInt(localStorage.getItem('currency_monit_module_width')) || 1400;
 
     //openNewTab (window.location.origin + '/rml9-web-module/index.html', {
-    openNewTab ((window.location.origin + '/currency-monit/', {
+    openNewTab (('localhost:10500/currency-monit/', {
       position: 'center',
       height: currencyMonitModuleHeight,
       width: currencyMonitModuleWidth,
diff --git a/lib/main.js b/lib/main.js
index 63e61b0..b4673af 100755
--- a/lib/main.js
+++ b/lib/main.js
@@ -18,8 +18,7 @@ module.exports = (duniterServer, host, port) => co(function *() {
   const idtyWindow = tabParameters[8];
   const sigQty = tabParameters[7];
   const stepMax = tabParameters[12];
-  console.log("currency-monit started");
-  console.log("__dirname = %s", __dirname);
+  console.log("module currency-monit started");
   
   // Define cache
   var cache = {
-- 
GitLab


From 60908ade11353c77ba7318976a14deb0b2585eee Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 7 Jun 2017 20:59:50 +0200
Subject: [PATCH 08/48] add nohelp option for fix #5

---
 routes/blockCount.js   |  2 ++
 routes/index.js        |  9 +++++++++
 routes/members.js      |  2 +-
 routes/willMembers.js  |  2 +-
 views/Chart.html       | 16 ++++++++--------
 views/about.html       | 16 +++++++++-------
 views/members.html     | 21 +++++++++++----------
 views/willMembers.html | 38 ++++++++++++++++++++------------------
 8 files changed, 61 insertions(+), 45 deletions(-)

diff --git a/routes/blockCount.js b/routes/blockCount.js
index 20f6bfe..5272c24 100755
--- a/routes/blockCount.js
+++ b/routes/blockCount.js
@@ -18,6 +18,7 @@ module.exports = (req, res, next) => co(function *() {
     var begin = req.query.begin >= 0 && req.query.begin || 0; // Default begin Value is zero
     var end = req.query.end >= 0 && req.query.end || -1; // Default Value is -1 (=current block)
     var format = req.query.format || 'HTML';
+    var help = req.query.help || 'yes';
     var data = req.query.data || 'nbBlocks';
     var perNode = (req.query.perNode == 'yes') ? 'yes':'no';
     var significantPercent = req.query.significantPercent || 3;
@@ -313,6 +314,7 @@ module.exports = (req, res, next) => co(function *() {
          tabBlockMembersSort, 
          begin, 
          end,
+	 help,
 	 data,
 	 perNode,
 	 description: ``,
diff --git a/routes/index.js b/routes/index.js
index 9d2db0d..ec4dc7c 100755
--- a/routes/index.js
+++ b/routes/index.js
@@ -27,6 +27,7 @@ Par exemple, home et about n'ont pas besoin de controleur
 ***************************************/
 app.get('/currency-monit/', (req, res)=> res.render('about.html', {
             host: req.headers.host.toString(),
+	    help: req.query.help,
 	    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`)
          })
  )
@@ -36,6 +37,7 @@ app.get('/currency-monit/', (req, res)=> res.render('about.html', {
 ***************************************/
 app.get('/currency-monit/about', (req, res)=> res.render('about.html', {
 	    host: req.headers.host.toString(),
+	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`)
          })
  )
@@ -48,6 +50,7 @@ app.get('/currency-monit/willMembers',
   (req, res)=> // Send html page
       res.status(200) // 200 n'est pas obligatoire, si on renvoie une réponse
          .render('willMembers.html', {
+	    help: req.query.help,
 	    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/willMembers_${req.query.lg||'fr'}.txt`)
          })
@@ -58,6 +61,7 @@ app.get('/currency-monit/willMembers',
 ***************************************/
 app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/members.js'),
   (req, res)=> res.render('members.html', {
+		    help: req.query.help,
 		    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
                     LANG: getLang(`${__dirname}/../lg/members_${req.query.lg||'fr'}.txt`)
                   })
@@ -67,6 +71,7 @@ app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require
 * Lister les anciens membres
 ***************************************/
 /*app.get('/currency-monit/wasMembers', require(__dirname + '/wasMembers.js'), (req, res)=> res.render('wasMembers.html', {
+	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/wasMembers_${lg}.txt`)
          })
@@ -76,6 +81,7 @@ app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require
 * Évolution du nombre de membres
 ***************************************/
 /*app.get('/currency-monit/membersCount', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/membersCount.js'), (req, res)=> res.render('Chart.html', {
+	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`)
          })
@@ -85,6 +91,7 @@ app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require
 * Lister les block en graph
 ***************************************/
 app.get('/currency-monit/blockCount', /*require('${__dirname}/../lib/updateCache.js'),*/ require(__dirname + '/blockCount.js'), (req, res)=> res.render('Chart.html', {
+	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/blockCount_${req.query.lg||'fr'}.txt`)
          })
@@ -94,6 +101,7 @@ app.get('/currency-monit/blockCount', /*require('${__dirname}/../lib/updateCache
 * Évolution de la masse monétaire totale
 ***************************************/
 app.get('/currency-monit/monetaryMass', require(__dirname + '/monetaryMass.js'), (req, res)=> res.render('Chart.html', {
+	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/monetaryMass_${req.query.lg||'fr'}.txt`)
          })
@@ -104,6 +112,7 @@ app.get('/currency-monit/monetaryMass', require(__dirname + '/monetaryMass.js'),
 * Solde d'une clé
 ***************************************/
 /*app.get('/currency-monit/pubkeyBalance', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
+	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/pubkeyBalance_${req.query.lg||'fr'}.txt`)
          })
diff --git a/routes/members.js b/routes/members.js
index c37916a..043ce0f 100755
--- a/routes/members.js
+++ b/routes/members.js
@@ -29,7 +29,7 @@ module.exports = (req, res, next) => co(function *() {
     var order = req.query.d && req.query.order || 'desc' // Valeur par défaut
     var sort_by = req.query.sort_by || "idtyWritten" // Valeur par défaut
     var pendingSigs = req.query.pendingSigs || "no";
-    var format = req.query.format || 'HTML'
+    var format = req.query.format || 'HTML';
     
     // Récupérer la liste des identités ayant actuellement le statut de membre
     const membersList = yield duniterServer.dal.peerDAL.query('SELECT `uid`,`pub`,`member`,`written_on` FROM i_index WHERE `member`=1');
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 45f93d6..56d77eb 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -30,7 +30,7 @@ module.exports = (req, res, next) => co(function *() {
     var sort_by = req.query.sort_by || "registrationPackage"; // Valeur par défaut
     var hideIdtyWithZeroCert = req.query.hideIdtyWithZeroCert || "no"; // Valeur par défaut
     var sortSig = req.query.sortSig || "Availability"; // Valeur par défaut
-    var format = req.query.format || 'HTML'
+    var format = req.query.format || 'HTML';
     
     // Récupérer la liste des identités en piscine
     const resultQueryIdtys = yield duniterServer.dal.peerDAL.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on` FROM identities_pending WHERE `member`=0');
diff --git a/views/Chart.html b/views/Chart.html
index 1e505f7..8c70684 100755
--- a/views/Chart.html
+++ b/views/Chart.html
@@ -4,13 +4,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <script src=${(host.substr(host.length-6,6) == '.onion') ? "http://722iprlhm7pw4mx7.onion/js/Chart.min.js":"https://librelois.fr/js/Chart.min.js"}></script>
 <table align="center" width="100%">
   <tr>
-    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
@@ -26,7 +26,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 ${form||''} <input type="submit" value="${LANG['SUBMIT_BUTTON']}"><br>${(typeof(form2) != 'undefined') ? form2:''}</form><br>
 
 <!-- Afficher la description -->
-${(typeof(description) != 'undefined') ? description:''}<br>
+${(typeof(description) != 'undefined' && help != 'no') ? description:''}<br>
 
 <!-- Afficher le graphique -->
 <canvas id="myChart"></canvas>
diff --git a/views/about.html b/views/about.html
index 58af527..64e44e3 100755
--- a/views/about.html
+++ b/views/about.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
@@ -32,3 +32,5 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/0.3.2">0.3.2</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
+<br>
+<div align="left">If you want you can <a href="/currency-monit/?lg=${MENU_LANG['LG']}&help=no">disable help</a>.</div><br>
\ No newline at end of file
diff --git a/views/members.html b/views/members.html
index 4843864..eafd18a 100755
--- a/views/members.html
+++ b/views/members.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
@@ -32,12 +32,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 </select> dans l\'ordre <select name="order">
 <option name="order" value ="asc">croissant
 <option name="order" value ="desc" ${order == 'desc' ? 'selected' : ''}>décroissant</select>
-
 <input type="submit" value="envoyer"><br>
-<br>
-${pendingSigs == 'yes' ? ` [inscriptible : date à partir de laquelle cette certification pourra être écrite compte tenu de sigPeriod]<br>` : ''}
 <input type="checkbox" name="pendingSigs" value="yes" ${pendingSigs == 'yes' ? 'checked' : ''}>Inclure les certifications en piscine.</form><br>
 
+<!-- Afficher la légende -->
+<br>
+${(pendingSigs == 'yes' && help != 'no') ? ` [inscriptible : date à partir de laquelle cette certification pourra être écrite compte tenu de sigPeriod]<br>` : ''}
+
 <!-- Afficher le currentBlockchainTimestamp -->
 <i>Temps Blockchain actuel : ${timestampToDatetime(currentBlockchainTimestamp)}.</i><br>
 <br>
diff --git a/views/willMembers.html b/views/willMembers.html
index 35231bf..8a40e58 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
@@ -39,17 +39,19 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <br>
 
 <!-- Afficher le currentBlockchainTimestamp et la légende -->
-<i><font color='DarkRed'>${LANG["SIG_PERIOD_LEGEND"]}</font><br>
-<font color='green'>${LANG["SIG_PERIOD_LEGEND2"]}</font></i><br>
-<br>
-<b>${LANG["HOW_TO_BECOME_MEMBER_TITLE"]}</b><br>
-${LANG["HOW_TO_BECOME_MEMBER_TEXT"]}<br>
-<br>
-<b>${LANG["DISTANCE_RULE_TITLE"]}</b><br>
-${LANG["DISTANCE_RULE_TXT"]}<br>
-<br>
-${LANG["BLOCKCHAIN_TIME"]} : <b>${timestampToDatetime(currentBlockchainTimestamp)}</b> (#<b>${currentBlockNumber}</b>).<br>
-${LANG["COUNT_READY_MEMBERS"]} : <b>${countMembersWithSigQtyValidCert}</b>.<br>
+${(help != 'no') ? `
+  <i><font color='DarkRed'>${LANG["SIG_PERIOD_LEGEND"]}</font><br>
+  <font color='green'>${LANG["SIG_PERIOD_LEGEND2"]}</font></i><br>
+  <br>
+  <b>${LANG["HOW_TO_BECOME_MEMBER_TITLE"]}</b><br>
+  ${LANG["HOW_TO_BECOME_MEMBER_TEXT"]}<br>
+  <br>
+  <b>${LANG["DISTANCE_RULE_TITLE"]}</b><br>
+  ${LANG["DISTANCE_RULE_TXT"]}<br>
+  <br>
+  ${LANG["BLOCKCHAIN_TIME"]} : <b>${timestampToDatetime(currentBlockchainTimestamp)}</b> (#<b>${currentBlockNumber}</b>).<br>
+  ${LANG["COUNT_READY_MEMBERS"]} : <b>${countMembersWithSigQtyValidCert}</b>.<br>
+`:''}
 <br>
 
 <!--On parcour toutes les identités-->
-- 
GitLab


From 3d4d425cb32ffae43771e79b9b2019565fd7ea7b Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 7 Jun 2017 22:02:51 +0200
Subject: [PATCH 09/48] if web-ui, use web-ui server

---
 index.js               |  9 ++----
 injection/menu.js      |  3 +-
 lib/main.js            | 12 ++++----
 lib/webserver.js       | 63 ++++++++++++++++++++++++------------------
 routes/monetaryMass.js | 20 +++++++++-----
 5 files changed, 59 insertions(+), 48 deletions(-)

diff --git a/index.js b/index.js
index 74d7dde..94d6786 100755
--- a/index.js
+++ b/index.js
@@ -46,7 +46,7 @@ module.exports = {
           yield startServices();
 
           // Main Loop
-          yield main(server, SERVER_HOST, SERVER_PORT);
+          yield main(server, SERVER_HOST, SERVER_PORT, null);
 
           // Wait forever, this is a permanent program
           yield new Promise(() => null);
@@ -59,12 +59,9 @@ module.exports = {
       },
       
       route: (app, server, conf, program, params) => {
-	// currency-monit parameters
-        const SERVER_HOST = params[0] || DEFAULT_HOST;
-        const SERVER_PORT = parseInt(params[1]) || DEFAULT_PORT;
-
         // Main Loop
-        main(server, SERVER_HOST, SERVER_PORT);
+        //main(server, SERVER_HOST, SERVER_PORT);
+	main(server, null, null, app);  // `app` est un serveur HTTP Express
 
         // Wait forever, this is a permanent program
         new Promise(() => null);
diff --git a/injection/menu.js b/injection/menu.js
index 7508bfa..0965867 100755
--- a/injection/menu.js
+++ b/injection/menu.js
@@ -16,8 +16,7 @@
     var currencyMonitModuleHeight = parseInt(localStorage.getItem('currency_monit_module_height')) || 1000;
     var currencyMonitModuleWidth = parseInt(localStorage.getItem('currency_monit_module_width')) || 1400;
 
-    //openNewTab (window.location.origin + '/rml9-web-module/index.html', {
-    openNewTab (('localhost:10500/currency-monit/', {
+    openNewTab (window.location.origin + '/currency-monit/', {
       position: 'center',
       height: currencyMonitModuleHeight,
       width: currencyMonitModuleWidth,
diff --git a/lib/main.js b/lib/main.js
index b4673af..4b72dc1 100755
--- a/lib/main.js
+++ b/lib/main.js
@@ -7,11 +7,11 @@ const duniter = require(__dirname + '/duniter.js');
 /****************************
  * Main algorithm
  */
-module.exports = (duniterServer, host, port) => co(function *() {
-
-  // Get currency parameters
-  const parameters = yield duniterServer.dal.peerDAL.query('SELECT `parameters` from block where `number`=0');
-  const tabParameters = parameters[0].parameters.split(":");
+module.exports = (duniterServer, host, port, appParente) => co(function *() {
+  
+  // Get currency name and parameters
+  const blockZero = yield duniterServer.dal.peerDAL.query('SELECT `currency`,`parameters` from block where `number`=0');
+  const tabParameters = blockZero[0].parameters.split(":");
   const sigValidity = tabParameters[6];
   const msValidity = tabParameters[11];
   const sigWindow = tabParameters[5];
@@ -37,7 +37,7 @@ module.exports = (duniterServer, host, port) => co(function *() {
   };
   
   // Specialized node's UI
-  let httpServer = webserver(host, port, duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache);
+  let httpServer = webserver(host, port, appParente, duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache);
   yield httpServer.openConnection();
 
 })
diff --git a/lib/webserver.js b/lib/webserver.js
index 04a9de6..ccea6e5 100755
--- a/lib/webserver.js
+++ b/lib/webserver.js
@@ -13,7 +13,7 @@ const bodyParser = require('body-parser');
 const routes = require(__dirname + '/../routes');
 const tpl = require(__dirname + '/tplit.js');
 
-module.exports = (host, port, duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache) => {
+module.exports = (host, port, appParente, duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache) => {
   
   var app = express();
   
@@ -51,31 +51,40 @@ module.exports = (host, port, duniterServer, sigValidity, msValidity, sigWindow,
   
   app.use( routes )
   
-  // Lancer le serveur web
-  let httpServer = http.createServer(app);
-  httpServer.on('error', function(err) {
-    httpServer.errorPropagates(err);
-  });
-  
-  return {
-    openConnection: () => co(function *() {
-      try {
-        yield Q.Promise((resolve, reject) => {
-          // Weird the need of such a hack to catch an exception...
-          httpServer.errorPropagates = function(err) {
-            reject(err);
-          };
+  // Si l'on ne dispose pas d'un serveur web parent, lancer notre propre serveur web
+  if ( appParente == null )
+  {
+    let httpServer = http.createServer(app);
+    httpServer.on('error', function(err) {
+      httpServer.errorPropagates(err);
+    });
+    
+    return {
+      openConnection: () => co(function *() {
+	try {
+	  yield Q.Promise((resolve, reject) => {
+	    // Weird the need of such a hack to catch an exception...
+	    httpServer.errorPropagates = function(err) {
+	      reject(err);
+	    };
 
-          httpServer.listen(port, host, (err) => {
-            if (err) return reject(err);
-            resolve(httpServer);
-          });
-        });
-        console.log('Server listening on http://' + host + ':' + port);
-      } catch (e) {
-        console.warn('Could NOT listen to http://' + host + ':' + port);
-        console.warn(e);
-      }
-    }),
-  };
+	    httpServer.listen(port, host, (err) => {
+	      if (err) return reject(err);
+	      resolve(httpServer);
+	    });
+	  });
+	  console.log('Server listening on http://' + host + ':' + port);
+	} catch (e) {
+	  console.warn('Could NOT listen to http://' + host + ':' + port);
+	  console.warn(e);
+	}
+      }),
+    };
+  }
+  else
+  {
+    appParent.use("/currency-monit", app);
+  }
+  
+  
 };
diff --git a/routes/monetaryMass.js b/routes/monetaryMass.js
index 0d21b35..cf5fd5d 100755
--- a/routes/monetaryMass.js
+++ b/routes/monetaryMass.js
@@ -76,15 +76,21 @@ module.exports = (req, res, next) => co(function *() {
       var massByMembers = req.query.massByMembers == 'no' ? 'no' : 'yes';
       var type = req.query.type == 'linear' ? 'linear' : 'logarithmic';
       
-      // Define max yAxes 
-      var maxYAxes = 3743;
-      if (unit == "quantitative") { maxYAxes = maxYAxes*currentDividend/100; }
-      if (massByMembers == "no") { maxYAxes = maxYAxes*tabCurrency[tabCurrency.length-1].membersCount; }
+      
     
       // Define full currency description
-      var fullCurrency = "The currency will be full when the money supply by member will be worth 3743 DU (because 1/c * dtReeval = 1/4,88% * 182,625j = 3743DU)<br>";
-	fullCurrency += "Currently, 1 DU<sub>ğ1</sub> = <b>"+(currentDividend/100)+"</b> Ğ1 and we have <b>"+tabCurrency[tabCurrency.length-1].membersCount+"</b> members. Thus in full currency we would have a total money supply of <b>"
-	  +(3743*currentDividend*tabCurrency[tabCurrency.length-1].membersCount/100)+"</b> Ğ1 (<b>"+(3743*currentDividend/100)+"</b> Ğ1/member)." ;
+      let meanMonetaryMassAtFullCurrency = Math.ceil((1/duniterServer.conf.c)*(duniterServer.conf.dtReeval / duniterServer.conf.dt));
+      var fullCurrency = "The currency will be full when the money supply by member will be worth <b>"+meanMonetaryMassAtFullCurrency
+	  +" DU</b> (because 1/c * dtReeval/dt = <b>"+meanMonetaryMassAtFullCurrency+" DU</b>)<br>"
+	  +"Currently, 1 DU<sub>"+duniterServer.conf.currency+"</sub> = <b>"+(currentDividend/100)+"</b> "+duniterServer.conf.currency+" and we have <b>"
+	  +tabCurrency[tabCurrency.length-1].membersCount+"</b> members. Thus in full currency we would have a total money supply of <b>"
+	  +(meanMonetaryMassAtFullCurrency*currentDividend*tabCurrency[tabCurrency.length-1].membersCount/100)+"</b> "+duniterServer.conf.currency
+	  +" (<b>"+(meanMonetaryMassAtFullCurrency*currentDividend/100)+"</b> "+duniterServer.conf.currency+"/member)." ;
+	  
+      // Define max yAxes
+      var maxYAxes = meanMonetaryMassAtFullCurrency;
+      if (unit == "quantitative") { maxYAxes = maxYAxes*currentDividend/100; }
+      if (massByMembers == "no") { maxYAxes = maxYAxes*tabCurrency[tabCurrency.length-1].membersCount; }
       
       res.locals = {
 	 host: req.headers.host.toString(),
-- 
GitLab


From ee66a3c45add1ed1e4c5d19f10b1781460876492 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 7 Jun 2017 22:38:14 +0200
Subject: [PATCH 10/48] use own webserver in cli mode

---
 lib/webserver.js       |  2 +-
 routes/index.js        | 18 +++++++++---------
 views/Chart.html       | 14 +++++++-------
 views/about.html       | 16 ++++++++--------
 views/members.html     | 14 +++++++-------
 views/willMembers.html | 14 +++++++-------
 6 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/lib/webserver.js b/lib/webserver.js
index ccea6e5..8273071 100755
--- a/lib/webserver.js
+++ b/lib/webserver.js
@@ -83,7 +83,7 @@ module.exports = (host, port, appParente, duniterServer, sigValidity, msValidity
   }
   else
   {
-    appParent.use("/currency-monit", app);
+    appParente.use("/currency-monit", app);
   }
   
   
diff --git a/routes/index.js b/routes/index.js
index ec4dc7c..bfdbffe 100755
--- a/routes/index.js
+++ b/routes/index.js
@@ -25,7 +25,7 @@ Par exemple, home et about n'ont pas besoin de controleur
 /***************************************
 * Home Page
 ***************************************/
-app.get('/currency-monit/', (req, res)=> res.render('about.html', {
+app.get('/', (req, res)=> res.render('about.html', {
             host: req.headers.host.toString(),
 	    help: req.query.help,
 	    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`)
@@ -35,7 +35,7 @@ app.get('/currency-monit/', (req, res)=> res.render('about.html', {
 /***************************************
 * About Page
 ***************************************/
-app.get('/currency-monit/about', (req, res)=> res.render('about.html', {
+app.get('/about', (req, res)=> res.render('about.html', {
 	    host: req.headers.host.toString(),
 	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`)
@@ -45,7 +45,7 @@ app.get('/currency-monit/about', (req, res)=> res.render('about.html', {
 /***************************************
 * Lister les futurs membres
 ***************************************/
-app.get('/currency-monit/willMembers', 
+app.get('/willMembers', 
   require(__dirname + '/willMembers.js'), // the route controler
   (req, res)=> // Send html page
       res.status(200) // 200 n'est pas obligatoire, si on renvoie une réponse
@@ -59,7 +59,7 @@ app.get('/currency-monit/willMembers',
 /***************************************
 * Lister les membres
 ***************************************/
-app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/members.js'),
+app.get('/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/members.js'),
   (req, res)=> res.render('members.html', {
 		    help: req.query.help,
 		    MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
@@ -70,7 +70,7 @@ app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require
 /***************************************
 * Lister les anciens membres
 ***************************************/
-/*app.get('/currency-monit/wasMembers', require(__dirname + '/wasMembers.js'), (req, res)=> res.render('wasMembers.html', {
+/*app.get('/wasMembers', require(__dirname + '/wasMembers.js'), (req, res)=> res.render('wasMembers.html', {
 	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/wasMembers_${lg}.txt`)
@@ -80,7 +80,7 @@ app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require
 /***************************************
 * Évolution du nombre de membres
 ***************************************/
-/*app.get('/currency-monit/membersCount', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/membersCount.js'), (req, res)=> res.render('Chart.html', {
+/*app.get('/membersCount', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/membersCount.js'), (req, res)=> res.render('Chart.html', {
 	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`)
@@ -90,7 +90,7 @@ app.get('/currency-monit/members', /*require('../lib/updateCache.js'),*/ require
 /***************************************
 * Lister les block en graph
 ***************************************/
-app.get('/currency-monit/blockCount', /*require('${__dirname}/../lib/updateCache.js'),*/ require(__dirname + '/blockCount.js'), (req, res)=> res.render('Chart.html', {
+app.get('/blockCount', /*require('${__dirname}/../lib/updateCache.js'),*/ require(__dirname + '/blockCount.js'), (req, res)=> res.render('Chart.html', {
 	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/blockCount_${req.query.lg||'fr'}.txt`)
@@ -100,7 +100,7 @@ app.get('/currency-monit/blockCount', /*require('${__dirname}/../lib/updateCache
 /***************************************
 * Évolution de la masse monétaire totale
 ***************************************/
-app.get('/currency-monit/monetaryMass', require(__dirname + '/monetaryMass.js'), (req, res)=> res.render('Chart.html', {
+app.get('/monetaryMass', require(__dirname + '/monetaryMass.js'), (req, res)=> res.render('Chart.html', {
 	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/monetaryMass_${req.query.lg||'fr'}.txt`)
@@ -111,7 +111,7 @@ app.get('/currency-monit/monetaryMass', require(__dirname + '/monetaryMass.js'),
 /***************************************
 * Solde d'une clé
 ***************************************/
-/*app.get('/currency-monit/pubkeyBalance', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
+/*app.get('/pubkeyBalance', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
 	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/pubkeyBalance_${req.query.lg||'fr'}.txt`)
diff --git a/views/Chart.html b/views/Chart.html
index 8c70684..c5ee51f 100755
--- a/views/Chart.html
+++ b/views/Chart.html
@@ -4,13 +4,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <script src=${(host.substr(host.length-6,6) == '.onion') ? "http://722iprlhm7pw4mx7.onion/js/Chart.min.js":"https://librelois.fr/js/Chart.min.js"}></script>
 <table align="center" width="100%">
   <tr>
-    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
diff --git a/views/about.html b/views/about.html
index 64e44e3..c8dd7a2 100755
--- a/views/about.html
+++ b/views/about.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
@@ -33,4 +33,4 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-<div align="left">If you want you can <a href="/currency-monit/?lg=${MENU_LANG['LG']}&help=no">disable help</a>.</div><br>
\ No newline at end of file
+<div align="left">If you want you can <a href="?lg=${MENU_LANG['LG']}&help=no">disable help</a>.</div><br>
\ No newline at end of file
diff --git a/views/members.html b/views/members.html
index eafd18a..4760960 100755
--- a/views/members.html
+++ b/views/members.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
diff --git a/views/willMembers.html b/views/willMembers.html
index 8a40e58..3503253 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -3,13 +3,13 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
-    <td><a href="/currency-monit/willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
-    <td><a href="/currency-monit/members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/currency-monit/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
-    <td><a href="/currency-monit/blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
-    <td><a href="/currency-monit/monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="/currency-monit/pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-    <td><a href="/currency-monit/about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
+    <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+    <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+    <!-- <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+    <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
 	<select name="lg" onchange="this.form.submit()">
-- 
GitLab


From 2d83d311b75148f4f4bd761452fb7d18134a5c8f Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Thu, 8 Jun 2017 01:17:18 +0200
Subject: [PATCH 11/48] change version to module-0.1

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index c8dd7a2..2501c90 100755
--- a/views/about.html
+++ b/views/about.html
@@ -29,7 +29,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/0.3.2">0.3.2</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.1">module-0.1</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From d05428fd8226ae470fc5a94772aa0b54095775ae Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 14 Jun 2017 14:06:52 +0200
Subject: [PATCH 12/48] fix minor bugs

---
 index.js                |  2 +-
 injection/menu.js       |  4 ++--
 lib/main.js             | 51 ++++++++++++++++++++++++++++++-----------
 lib/webserver.js        | 14 +++++------
 package.json            |  1 +
 routes/pubkeyBalance.js |  2 +-
 views/willMembers.html  |  2 +-
 7 files changed, 51 insertions(+), 25 deletions(-)

diff --git a/index.js b/index.js
index 94d6786..8fad0e2 100755
--- a/index.js
+++ b/index.js
@@ -46,7 +46,7 @@ module.exports = {
           yield startServices();
 
           // Main Loop
-          yield main(server, SERVER_HOST, SERVER_PORT, null);
+          yield main(server, SERVER_HOST, SERVER_PORT, null, program);
 
           // Wait forever, this is a permanent program
           yield new Promise(() => null);
diff --git a/injection/menu.js b/injection/menu.js
index 0965867..8521926 100755
--- a/injection/menu.js
+++ b/injection/menu.js
@@ -7,7 +7,7 @@
 
   window.uiModules['duniter-currency-monit'] = {
     menuIconClass: 'fa-signal',
-    menuLabel: 'Ğune Monit',
+    menuLabel: 'Currency Monit',
     menuOpen: openCurrencyMonitModule
   }
 
@@ -16,7 +16,7 @@
     var currencyMonitModuleHeight = parseInt(localStorage.getItem('currency_monit_module_height')) || 1000;
     var currencyMonitModuleWidth = parseInt(localStorage.getItem('currency_monit_module_width')) || 1400;
 
-    openNewTab (window.location.origin + '/currency-monit/', {
+    window.openModule ('/currency-monit/', {
       position: 'center',
       height: currencyMonitModuleHeight,
       width: currencyMonitModuleWidth,
diff --git a/lib/main.js b/lib/main.js
index 4b72dc1..3431aa7 100755
--- a/lib/main.js
+++ b/lib/main.js
@@ -1,24 +1,46 @@
 "use strict";
 
 const co = require('co');
+const sqlite3 = require('sqlite3').verbose();
+const home = require('os').homedir();
+
 const webserver = require(__dirname + '/webserver.js');
 const duniter = require(__dirname + '/duniter.js');
 
 /****************************
  * Main algorithm
  */
-module.exports = (duniterServer, host, port, appParente) => co(function *() {
-  
-  // Get currency name and parameters
-  const blockZero = yield duniterServer.dal.peerDAL.query('SELECT `currency`,`parameters` from block where `number`=0');
-  const tabParameters = blockZero[0].parameters.split(":");
-  const sigValidity = tabParameters[6];
-  const msValidity = tabParameters[11];
-  const sigWindow = tabParameters[5];
-  const idtyWindow = tabParameters[8];
-  const sigQty = tabParameters[7];
-  const stepMax = tabParameters[12];
-  console.log("module currency-monit started");
+module.exports = (duniterServer, host, port, appParente, program) => co(function *() {
+  
+  /*// Create monit database
+  const configPath = home+'/.config/duniter/'+program.mdb+'/';
+   var db = new sqlite3.Database(configPath + 'currency-monit.db');
+  
+  // Fill monit database
+  db.serialize(function() {
+    db.run("CREATE TABLE lorem (info TEXT)");
+  
+    var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
+    for (var i = 0; i < 10; i++) {
+	stmt.run("Ipsum " + i);
+    }
+    stmt.finalize();
+  
+    db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
+	console.log(row.id + ": " + row.info);
+    });
+  });
+  db.close();
+  
+  // Read monit database
+  const db2 = new sqlite3.Database(configPath + 'currency-monit.db');
+  db2.serialize(function() {
+    db2.all("SELECT * FROM user_info", function(err, rows) {
+      if (err) { console.error(err); }
+      else { for (let i=0;i<rows.length;i++) { console.log("%s:%s", rows[i].id, rows[i].info); } }
+    });
+  });
+  db2.close();*/
   
   // Define cache
   var cache = {
@@ -35,9 +57,12 @@ module.exports = (duniterServer, host, port, appParente) => co(function *() {
     pub_index: new Array(),
     blockchain: new Array()
   };
+    
+  // Confirm started
+  console.log("module currency-monit started");
   
   // Specialized node's UI
-  let httpServer = webserver(host, port, appParente, duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache);
+  let httpServer = webserver(host, port, appParente, duniterServer, cache);
   yield httpServer.openConnection();
 
 })
diff --git a/lib/webserver.js b/lib/webserver.js
index 8273071..c28901a 100755
--- a/lib/webserver.js
+++ b/lib/webserver.js
@@ -13,7 +13,7 @@ const bodyParser = require('body-parser');
 const routes = require(__dirname + '/../routes');
 const tpl = require(__dirname + '/tplit.js');
 
-module.exports = (host, port, appParente, duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache) => {
+module.exports = (host, port, appParente, duniterServer, cache) => {
   
   var app = express();
   
@@ -38,12 +38,12 @@ module.exports = (host, port, appParente, duniterServer, sigValidity, msValidity
   app.set('view engine', 'html') // register the template engine
   
   app.locals.duniterServer = duniterServer
-  app.locals.sigValidity = sigValidity
-  app.locals.msValidity = msValidity
-  app.locals.sigWindow = sigWindow
-  app.locals.idtyWindow = idtyWindow
-  app.locals.sigQty = sigQty
-  app.locals.stepMax = stepMax
+  app.locals.sigValidity = duniterServer.conf.sigValidity
+  app.locals.msValidity = duniterServer.conf.msValidity
+  app.locals.sigWindow = duniterServer.conf.sigWindow
+  app.locals.idtyWindow = duniterServer.conf.idtyWindow
+  app.locals.sigQty = duniterServer.conf.sigQty
+  app.locals.stepMax = duniterServer.conf.stepMax
   app.locals.cache = cache
   
   app.locals.HTML_HEAD = fs.readFileSync(__dirname + '/../views/HEAD.html', 'utf-8')
diff --git a/package.json b/package.json
index 18b0386..c5e00dc 100755
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
     "request": "^2.81.0",
     "request-promise": "4.2.0",
     "rimraf": "^2.6.1",
+    "sqlite3": "3.1.x",
     "tmp": "^0.0.31",
     "underscore": "1.8.3",
     "ws": "1.1.1"
diff --git a/routes/pubkeyBalance.js b/routes/pubkeyBalance.js
index 2657e01..f8717bc 100755
--- a/routes/pubkeyBalance.js
+++ b/routes/pubkeyBalance.js
@@ -45,7 +45,7 @@ module.exports = (req, res, next) => co(function *() {
 	
 	// get all dividend created by pubkey1
 	var pubkey1Dividends = yield duniterServer.dal.peerDAL.query('SELECT `dividend`,`medianTime`,`number` FROM block WHERE `fork`=0 AND `dividend` > 0 '
-	  +'AND `medianTime` >=\''+joinersTimePubkey1[0].medianTime+'\' AND `medianTime` <=\''+cache.endBlock[0].medianTime+'\' '
+	  +'AND `medianTime` >\''+joinersTimePubkey1[0].medianTime+'\' AND `medianTime` <=\''+cache.endBlock[0].medianTime+'\' '
 	  +'ORDER BY `medianTime` ASC');
       }
       
diff --git a/views/willMembers.html b/views/willMembers.html
index 3503253..5e3bc1e 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -74,7 +74,7 @@ ${(help != 'no') ? `
       <tr>
         <td align="center" style="background:${idty.colorPending=color(idty.expires_on,idtyWindow,250)}">
         <!--<td align="center" style="background:\${colorPendingIdty}">-->
-          <a href="http://wotex.cgeek.fr/?to=${idty['uid']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
+          <a href="https://wotex.cgeek.fr/?to=${idty['uid']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
           ${idty['pubkey'].substring(0, 8)}
           <br>->${idty.pendingCertifications.length}
         </td>
-- 
GitLab


From 5a729f998270b574c1ec562e69af4eb92ff7d271 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 14 Jun 2017 14:08:56 +0200
Subject: [PATCH 13/48] version module-0.2

---
 package.json     | 4 ++--
 views/about.html | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index c5e00dc..353d689 100755
--- a/package.json
+++ b/package.json
@@ -24,13 +24,13 @@
     "ws": "1.1.1"
   },
   "devDependencies": {
-    "duniter": "1.3.2",
+    "duniter": "1.3.9",
     "duniter-keypair": "1.3.x",
     "duniter-bma": "1.3.x",
     "duniter-crawler": "1.3.x",
     "duniter-prover": "1.3.x"
   },
   "peerDependencies": {
-    "duniter": "1.3.2"
+    "duniter": "1.3.9"
   }
 }
diff --git a/views/about.html b/views/about.html
index 2501c90..2bebaa5 100755
--- a/views/about.html
+++ b/views/about.html
@@ -29,7 +29,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.1">module-0.1</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2">module-0.2</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From 8ab81b5a855364d9ff6d87f69aa1e293de512cee Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 14 Jun 2017 14:17:33 +0200
Subject: [PATCH 14/48] version module-0.2.1

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index 2bebaa5..35311bf 100755
--- a/views/about.html
+++ b/views/about.html
@@ -29,7 +29,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2">module-0.2</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.1">module-0.2.1</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From b4f1c096e62a2ec1ba9ae6eb533da1070b162669 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 14 Jun 2017 14:22:04 +0200
Subject: [PATCH 15/48] version module-0.2.1

---
 views/about.html | 1 -
 1 file changed, 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index 35311bf..a0dcff9 100755
--- a/views/about.html
+++ b/views/about.html
@@ -21,7 +21,6 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 </table>
 </select>
 
-
 </form>
 <hr>
 <div align="center">
-- 
GitLab


From a4fc7240c9aec6a621499c5efcefe38b8215f957 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Wed, 14 Jun 2017 15:10:40 +0200
Subject: [PATCH 16/48] module-0.2.2

---
 views/about.html | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/views/about.html b/views/about.html
index a0dcff9..b3b5a6d 100755
--- a/views/about.html
+++ b/views/about.html
@@ -19,7 +19,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
     </td>
 </tr>
 </table>
-</select>
+</select> 
 
 </form>
 <hr>
@@ -28,7 +28,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.1">module-0.2.1</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.2">module-0.2.2</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From 98ca95ab164ab7369db084d1ec0d6f5ab3e9df35 Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Tue, 20 Jun 2017 14:07:23 +0200
Subject: [PATCH 17/48] [enh] Add "distance" column

---
 lg/willMembers_en.txt  |  3 +++
 lg/willMembers_fr.txt  |  3 +++
 routes/willMembers.js  | 31 ++++++++++++++++++++++++++++---
 views/willMembers.html |  5 ++++-
 4 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/lg/willMembers_en.txt b/lg/willMembers_en.txt
index 666f596..f888406 100755
--- a/lg/willMembers_en.txt
+++ b/lg/willMembers_en.txt
@@ -24,6 +24,9 @@ COL_2 Identity created
 COL_3 Identity expires
 COL_4 List of received certifications (recent -> old)
 COL_4_WITH_AVAIlABILITY_SORT List of received certifications (by availability time)
+COL_DISTANCE distance
+COL_DISTANCE_isOutdistanced KO
+COL_DISTANCE_isNotOutdistanced OK
 SIG_PERIOD_OK available
 INVALID_BLOCKSTAMP invalid blockstamp
 LAST_TR1  total
diff --git a/lg/willMembers_fr.txt b/lg/willMembers_fr.txt
index 2eced34..d720a6a 100755
--- a/lg/willMembers_fr.txt
+++ b/lg/willMembers_fr.txt
@@ -24,6 +24,9 @@ COL_2 création identité
 COL_3 expiration identité
 COL_4 liste des certifications reçues (récentes -> anciennes)
 COL_4_WITH_AVAIlABILITY_SORT liste des certifications reçues (par date de disponibilité)
+COL_DISTANCE distance
+COL_DISTANCE_isOutdistanced KO
+COL_DISTANCE_isNotOutdistanced OK
 SIG_PERIOD_OK disponible
 INVALID_BLOCKSTAMP blockstamp incorrect
 LAST_TR1  total
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 56d77eb..0444f3a 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -16,6 +16,9 @@ module.exports = (req, res, next) => co(function *() {
     const currentBlockchainTimestamp = resultQueryCurrentBlock[0].medianTime;
     const currentBlockNumber = resultQueryCurrentBlock[0].number;
     const currentBlockHash = resultQueryCurrentBlock[0].hash;
+
+    // Dictionnaire pubkey => wid (wotb ID)
+    const widsCache = {}
     
     // Initaliser les variables
     var errors = "";
@@ -62,7 +65,7 @@ module.exports = (req, res, next) => co(function *() {
       // récupérer l'ensemble des certifications en attente destinées à l'identité courante
       let tmpQueryPendingCertifsList = yield duniterServer.dal.peerDAL.query(
 	'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+resultQueryIdtys[i].pubkey+'\' AND `target`=\''+resultQueryIdtys[i].hash+'\' ORDER BY `expires_on` DESC');
-	  
+
       // Récupérer les uid des émetteurs des certifications reçus par l'utilisateur
       // Et stocker les uid et dates d'expiration dans un tableau
       for (let j=0;j<tmpQueryPendingCertifsList.length;j++)
@@ -74,6 +77,13 @@ module.exports = (req, res, next) => co(function *() {
 	  let tmpQueryGetUidIssuerPendingCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpQueryPendingCertifsList[j].from+'\' LIMIT 1');
 	  if ( tmpQueryGetUidIssuerPendingCert.length > 0 )
 	  {
+	    // Mémoriser le wid
+      const pubkeyFrom = tmpQueryPendingCertifsList[j].from
+      if (!widsCache[pubkeyFrom]) {
+        // Récupère le wotb_id depuis la table d'index globale
+        widsCache[pubkeyFrom] = (yield duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [pubkeyFrom]))[0].wotb_id
+      }
+
 	    // Vérifier si le blockstamp est correct
 	    var validBlockStamp = false;
 	    if (emittedBlock[0].hash == tmpQueryPendingCertifsList[j].block_hash)
@@ -101,6 +111,7 @@ module.exports = (req, res, next) => co(function *() {
 	      if (tmpQueryPendingCertifsList[j].expires_on > currentBlockchainTimestamp)
 	      {
 		idtysPendingCertifsList[i].push({
+      wid: widsCache[pubkeyFrom],
 		  from: tmpQueryGetUidIssuerPendingCert[0].uid,
 		  pubkey: tmpQueryPendingCertifsList[j].from,
 		  blockNumber: tmpQueryPendingCertifsList[j].block_number,
@@ -121,7 +132,7 @@ module.exports = (req, res, next) => co(function *() {
       // calculate countMembersWithSigQtyValidCert
       if ( identitiesList[i].nbValidPendingCert >= sigQty) { countMembersWithSigQtyValidCert++; }
     }
-      
+
     // Si demandé, retrier les, certifications par date de disponibilité
     if (sortSig == "Availability")
     {
@@ -149,6 +160,7 @@ module.exports = (req, res, next) => co(function *() {
         
           // Push min value on sort table
           idtysPendingCertifsListSort[i].push({
+            wid: idtysPendingCertifsList[i][idMin].wid,
             from: idtysPendingCertifsList[i][idMin].from,
             blockNumber: idtysPendingCertifsList[i][idMin].blockNumber,
             timestampExpire: idtysPendingCertifsList[i][idMin].timestampExpire,
@@ -199,7 +211,19 @@ module.exports = (req, res, next) => co(function *() {
         }
     }
     else { errors += "<p>ERREUR : param <i>sort_by</i> invalid !</p>"; }
-    
+
+    // Tester la distance à l'aide des certifications disponibles
+    const wotb = duniterServer.dal.wotb.memCopy();
+    const conf = duniterServer.conf
+    const dSen = Math.ceil(Math.pow(resultQueryCurrentBlock[0].membersCount, 1 / conf.stepMax));
+    const pendingIdtyWID = wotb.addNode()
+    for (const cert of idtysPendingCertifsList) {
+      wotb.addLink(cert.wid, pendingIdtyWID)
+    }
+    const isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
+    // Nettoie la wot temporaire
+    wotb.clear();
+
     // Trier les identités par ordre decroissant du critère sort_by
     for (var i=0;i<identitiesList.length;i++)
     {
@@ -235,6 +259,7 @@ module.exports = (req, res, next) => co(function *() {
           BlockNumber: identitiesList[idMax].BlockNumber,
           expires_on: identitiesList[idMax].expires_on,
           nbValidPendingCert: identitiesList[idMax].nbValidPendingCert,
+          isOutdistanced,
           pendingCertifications: idtysPendingCertifsList[idMax]
           });
         }
diff --git a/views/willMembers.html b/views/willMembers.html
index 5e3bc1e..db95ecd 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -61,7 +61,7 @@ ${(help != 'no') ? `
   <!-- Printer les nom des colonnes-->
   <tr>
     <td align='center'>${LANG['COL_1']}</td><td align='center'>${LANG['COL_2']}</td>
-    <td align='center'>${LANG['COL_3']}</td><td style="background:#000000">-</td>
+    <td align='center'>${LANG['COL_3']}</td><td align='center'>${LANG['COL_DISTANCE']}</td><td style="background:#000000">-</td>
     <td align='center' colspan="${nbMaxCertifs}">${sortSig == "Availability" 
                                                   ? LANG['COL_4_WITH_AVAIlABILITY_SORT']
                                                   : LANG['COL_4']}</td>
@@ -83,6 +83,9 @@ ${(help != 'no') ? `
         </td>
         <td align='center' style="background:${idty.colorPending}">
         ${timestampToDatetime(idty.expires_on)}</td>
+        <td align='center' style="background:${idty.colorPending}">
+          <span style="color: ${idty.isOutdistanced ? 'red' : 'green' }">${idty.isOutdistanced ? LANG['COL_DISTANCE_isOutdistanced'] : LANG['COL_DISTANCE_isNotOutdistanced'] }</span>
+        </td>
         <td style="background:#000000">-</td>
         
         <!--printer les certifications-->
-- 
GitLab


From 11098c4a00fe793ba9739aeaec3046528e06346b Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Tue, 20 Jun 2017 14:30:15 +0200
Subject: [PATCH 18/48] [enh] Add "--wotexURL" parameter in Duniter config

---
 index.js               | 20 ++++++++++++++++++++
 routes/willMembers.js  |  2 ++
 views/willMembers.html |  2 +-
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/index.js b/index.js
index 8fad0e2..c408d0b 100755
--- a/index.js
+++ b/index.js
@@ -29,6 +29,26 @@ const DEFAULT_PORT = 10500;
 module.exports = {
     duniter: {
 
+      config: {
+        onLoading: (conf, program) => co(function*() {
+
+          // Define duniter-currency-monit parameters namespace
+          const obj = conf['duniter-currency-monit'] = conf['duniter-currency-monit'] || {}
+
+          // We override the wotexURL parameter by the one given
+          obj.wotexURL = program.wotexURL || obj.wotexURL
+
+          // Default value
+          if (!obj.wotexURL) {
+            obj.wotexURL = '#!'
+          }
+        })
+      },
+
+      cliOptions: [
+        { value: '--wotexURL <url>', desc: 'URL of Wotex service for UID links on willMembers page'}
+      ],
+
       cli: [{
         name: 'currency-monit [host] [port]',
         desc: 'Start duniter with module currency-monit',
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 0444f3a..0524fc9 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -302,6 +302,8 @@ module.exports = (req, res, next) => co(function *() {
         idtyWindow,
         nbMaxCertifs,
 	countMembersWithSigQtyValidCert,
+
+        wotexURL: duniterServer.conf['duniter-currency-monit'].wotexURL,
         
         idtysListFiltered: idtysListOrdered.filter( idty=> 
               idty.expires_on < limitTimestamp
diff --git a/views/willMembers.html b/views/willMembers.html
index db95ecd..8ae9293 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -74,7 +74,7 @@ ${(help != 'no') ? `
       <tr>
         <td align="center" style="background:${idty.colorPending=color(idty.expires_on,idtyWindow,250)}">
         <!--<td align="center" style="background:\${colorPendingIdty}">-->
-          <a href="https://wotex.cgeek.fr/?to=${idty['uid']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
+          <a href="${wotexURL}?to=${idty['uid']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
           ${idty['pubkey'].substring(0, 8)}
           <br>->${idty.pendingCertifications.length}
         </td>
-- 
GitLab


From c7555fb62a4c429c974d51f16b49e1e01b4a5d14 Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Tue, 20 Jun 2017 16:18:20 +0200
Subject: [PATCH 19/48] [enh] Certification UID is now also a link

---
 views/willMembers.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/willMembers.html b/views/willMembers.html
index 8ae9293..d43e432 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -93,7 +93,7 @@ ${(help != 'no') ? `
           ${ (j<nbMaxCertifs) ? `
             <td align="center" style="background:${(cert.validBlockStamp) ? color(cert.timestampExpire,sigWindow,250) : '#FF8000'}">
             ${j==4?'<b>':''}
-	    ${cert['from']}
+        <a href="${wotexURL}?to=${cert['from']}&pending=on&mode=undefined">${cert['from']}</a>
 	    <br>${timestampToDatetime(cert.timestampExpire)}
 	    <br>#${cert['blockNumber']}
 	    ${ ( !cert.validBlockStamp || cert['timestampWritable'] > currentBlockchainTimestamp ) ? `
-- 
GitLab


From 70cd2b2f75b328619227116d8495e4a367776984 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 16:39:29 +0200
Subject: [PATCH 20/48] prepare memory cache to sqlite bdd

---
 lib/main.js            | 34 +++++-------------------
 lib/updateCache.js     | 59 +++++++++++++++++++++++++++++++++++-------
 lib/webserver.js       |  8 +++---
 routes/index.js        |  4 +--
 routes/membersCount.js |  2 +-
 views/Chart.html       |  2 +-
 views/about.html       |  2 +-
 views/members.html     |  2 +-
 views/willMembers.html |  2 +-
 9 files changed, 69 insertions(+), 46 deletions(-)

diff --git a/lib/main.js b/lib/main.js
index 3431aa7..1f194e5 100755
--- a/lib/main.js
+++ b/lib/main.js
@@ -12,40 +12,20 @@ const duniter = require(__dirname + '/duniter.js');
  */
 module.exports = (duniterServer, host, port, appParente, program) => co(function *() {
   
-  /*// Create monit database
-  const configPath = home+'/.config/duniter/'+program.mdb+'/';
-   var db = new sqlite3.Database(configPath + 'currency-monit.db');
-  
-  // Fill monit database
+  // Create monit database
+  const dbPath = home+'/.config/duniter/'+program.mdb+'/currency-monit.db';
+  var db = new sqlite3.Database(dbPath);
   db.serialize(function() {
-    db.run("CREATE TABLE lorem (info TEXT)");
-  
-    var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
-    for (var i = 0; i < 10; i++) {
-	stmt.run("Ipsum " + i);
-    }
-    stmt.finalize();
-  
-    db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
-	console.log(row.id + ": " + row.info);
-    });
+    db.run("CREATE TABLE if not exists blocks (number TEXT, timestamp TEXT, sentries INT)");
   });
   db.close();
   
-  // Read monit database
-  const db2 = new sqlite3.Database(configPath + 'currency-monit.db');
-  db2.serialize(function() {
-    db2.all("SELECT * FROM user_info", function(err, rows) {
-      if (err) { console.error(err); }
-      else { for (let i=0;i<rows.length;i++) { console.log("%s:%s", rows[i].id, rows[i].info); } }
-    });
-  });
-  db2.close();*/
-  
   // Define cache
   var cache = {
     lock : false,
     beginBlock: null,
+    currentBlockNumber : 0,
+    currentBlockTime: 0,
     endBlock: null,
     step: null,
     stepUnit: null,
@@ -62,7 +42,7 @@ module.exports = (duniterServer, host, port, appParente, program) => co(function
   console.log("module currency-monit started");
   
   // Specialized node's UI
-  let httpServer = webserver(host, port, appParente, duniterServer, cache);
+  let httpServer = webserver(host, port, appParente, duniterServer, cache, dbPath);
   yield httpServer.openConnection();
 
 })
diff --git a/lib/updateCache.js b/lib/updateCache.js
index 227d087..606d28d 100755
--- a/lib/updateCache.js
+++ b/lib/updateCache.js
@@ -1,6 +1,7 @@
 "use strict";
 
 const co = require('co');
+const sqlite3 = require('sqlite3').verbose();
 
 const STEP_COUNT_MIN = 4;
 const STEP_COUNT_MAX = 150;
@@ -11,7 +12,7 @@ const STEP_COUNT_MAX = 150;
      */
 module.exports = (req, res, next) => co(function *() {
   
-  var { duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache } = req.app.locals
+  var { duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, sigQty, stepMax, cache, dbPath } = req.app.locals
 
   try {
     // if updateCache working, wait
@@ -142,17 +143,23 @@ module.exports = (req, res, next) => co(function *() {
     cache.stepTime = parseInt(cache.step)*unitTime;
 
     // if new blocks, update cache
-    if ( parseInt(cache.endBlock[0].number) >= cache.blockchain.length )
+    if ( parseInt(cache.endBlock[0].number) >= cache.currentBlockNumber )
     {
-      let previousCacheTime = (cache.blockchain.length > 0) ? cache.blockchain[cache.blockchain.length-1].medianTime:0;
+      // let previousCacheTime = (cache.blockchain.length > 0) ? cache.blockchain[cache.blockchain.length-1].medianTime:0;
       var newBlocks = yield duniterServer.dal.peerDAL.query(
-	'SELECT `hash`,`membersCount`,`medianTime`,`number`,`dividend`,`transactions`,`joiners`,`certifications`,`issuersCount` FROM block WHERE `fork`=0 AND `medianTime` > '+previousCacheTime+' AND `medianTime` <= '+cache.endBlock[0].medianTime+' ORDER BY `medianTime` ASC');
+	'SELECT `hash`,`membersCount`,`medianTime`,`number`,`dividend`,`transactions`,`joiners`,`certifications`,`issuersCount` FROM block WHERE `fork`=0 AND `medianTime` > '+cache.currentBlockTime+' AND `medianTime` <= '+cache.endBlock[0].medianTime+' ORDER BY `medianTime` ASC');
       
-      if ( cache.blockchain.length > 0 && (newBlocks.length-1) != (parseInt(cache.endBlock[0].number)-cache.blockchain.length) )
+      if ( cache.currentBlockNumber > 0 && (newBlocks.length-1) != (parseInt(cache.endBlock[0].number)-cache.currentBlockNumber) )
       {
 	res.status(500).send('<pre>Fatal Error : newBlocks.length != (endBlock[0].number-cache.blockchain.length)</pre>');
       }
       
+      // Initialise bddBuffer
+      let bddBuffer = {
+	blocks: new Array()
+      };
+      
+      
       for (let b=0;b<newBlocks.length;b++)
       {
 	// Init let variables
@@ -183,14 +190,14 @@ module.exports = (req, res, next) => co(function *() {
 	}
 	
 	// parse and push transactions
-	transactions = JSON.parse(newBlocks[b].transactions);
+	/*transactions = JSON.parse(newBlocks[b].transactions);
 	for (let t=0;t<transactions.length;t++)
 	{
 	  // Calculate inputsSum
 	  let inputsSum = 0;
 	  for (let i=0;i<transactions[t].inputs.length;i++)
 	  {
-	    console.log("(b, t, i) = %s, %s, %s", b, t, i);
+	    //console.log("(b, t, i) = %s, %s, %s", b, t, i);
 	    let input = transactions[t].inputs[i].split(":");
 	    inputsSum += (parseInt(input[0])*Math.pow(10, parseInt(input[1])));
 	  }
@@ -320,7 +327,7 @@ module.exports = (req, res, next) => co(function *() {
 	    cache.pubkeys[cache.pub_index[issuer]].balance = 0;
 	  }
 	}
-	
+	*/
 	// parse and split joiners
 	joiners = JSON.parse(newBlocks[b].joiners);
 	for (let j=0;j<joiners.length;j++)
@@ -361,6 +368,18 @@ module.exports = (req, res, next) => co(function *() {
 	  if (cache.pubkeys[cache.pub_index[certifications[c][0]]].writtenCerts.length == cache.Yn && cache.pubkeys[cache.pub_index[certifications[c][0]]].receivedCerts.length >= cache.Yn) { newSentries++; }
 	  if (cache.pubkeys[cache.pub_index[certifications[c][1]]].writtenCerts.length >= cache.Yn && cache.pubkeys[cache.pub_index[certifications[c][1]]].receivedCerts.length == cache.Yn) { newSentries++; }
 	}
+	
+	// Add block to bddBuffer
+	cache.currentBlockNumber++;
+	cache.currentBlockTime = newBlocks[b].medianTime;
+	if (newSentries > 0)
+	{
+	  bddBuffer.blocks.push({
+	    number: cache.currentBlockNumber,
+	    time: cache.currentBlockTime,
+	    newSentries: newSentries
+	  });
+	}
 
 	cache.blockchain.push({
 	  hash: newBlocks[b].hash,
@@ -370,7 +389,29 @@ module.exports = (req, res, next) => co(function *() {
       }
       
       // DEBUG BALANCE
-      console.log("cache.destroyAmount = %s", cache.destroyAmount);
+      //console.log("cache.destroyAmount = %s", cache.destroyAmount);
+      
+      // Write bddBuffer to currency-monit bdd 
+      let db = new sqlite3.Database(dbPath);
+      db.serialize(function() {
+	let sentriesCount = 0;
+	db.all("SELECT sentries FROM blocks ORDER BY timestamp DESC LIMIT 1", function(err, rows) {
+	      if (rows.length > 0) { sentriesCount = rows.sentries; }
+	    });
+	var stmt = db.prepare("INSERT INTO blocks VALUES (?,?,?)");
+	for (let i=0;i<bddBuffer.blocks.length;i++)
+	{
+	  console.log("bddBuffer[%s] = (%s,%s,%s)", i, bddBuffer.blocks[i].number, bddBuffer.blocks[i].time, bddBuffer.blocks[i].newSentries);
+	  sentriesCount += bddBuffer.blocks[i].newSentries;
+	  stmt.run(bddBuffer.blocks[i].number, bddBuffer.blocks[i].time, sentriesCount);
+	}
+	stmt.finalize();
+	  
+	    /*db.each("SELECT number, timestamp, sentries FROM blocks", function(err, row) {
+		console.log("#" + row.number + ":" + row.timestamp + ":" + row.sentries);
+	    });*/
+      });
+      db.close();
     }
     
     // Unlock cache
diff --git a/lib/webserver.js b/lib/webserver.js
index c28901a..c7d945c 100755
--- a/lib/webserver.js
+++ b/lib/webserver.js
@@ -13,17 +13,18 @@ const bodyParser = require('body-parser');
 const routes = require(__dirname + '/../routes');
 const tpl = require(__dirname + '/tplit.js');
 
-module.exports = (host, port, appParente, duniterServer, cache) => {
+module.exports = (host, port, appParente, duniterServer, cache, dbPath) => {
   
   var app = express();
   
   // Redirect stdout to access.log
-  const logFile = fs.createWriteStream(__dirname + '/access.log', { flags: 'a' });
+  /*const logFile = fs.createWriteStream(__dirname + '/access.log', { flags: 'a' });
   console.log = function () {
     logFile.write(util.format.apply(null, arguments) + '\n');
-  }
+  }*/
   //console.error = console.log;
   
+  
   app.use(morgan('\x1b[90m:remote-addr :remote-user [:date[clf]] :method :url HTTP/:http-version :status :res[content-length] - :response-time ms\x1b[0m', {
     stream: {
       write: function(message){
@@ -45,6 +46,7 @@ module.exports = (host, port, appParente, duniterServer, cache) => {
   app.locals.sigQty = duniterServer.conf.sigQty
   app.locals.stepMax = duniterServer.conf.stepMax
   app.locals.cache = cache
+  app.locals.dbPath = dbPath
   
   app.locals.HTML_HEAD = fs.readFileSync(__dirname + '/../views/HEAD.html', 'utf-8')
   app.locals.HTML_TOR_HEAD = fs.readFileSync(__dirname + '/../views/TOR_HEAD.html', 'utf-8')
diff --git a/routes/index.js b/routes/index.js
index bfdbffe..9bcefb5 100755
--- a/routes/index.js
+++ b/routes/index.js
@@ -80,12 +80,12 @@ app.get('/members', /*require('../lib/updateCache.js'),*/ require(__dirname + '/
 /***************************************
 * Évolution du nombre de membres
 ***************************************/
-/*app.get('/membersCount', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/membersCount.js'), (req, res)=> res.render('Chart.html', {
+app.get('/membersCount', require(__dirname + '/../lib/updateCache.js'), require(__dirname + '/membersCount.js'), (req, res)=> res.render('Chart.html', {
 	    help: req.query.help,
             MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
             LANG: getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`)
          })
- )*/
+ )
 
 /***************************************
 * Lister les block en graph
diff --git a/routes/membersCount.js b/routes/membersCount.js
index 6d76638..1e8dad0 100755
--- a/routes/membersCount.js
+++ b/routes/membersCount.js
@@ -83,7 +83,7 @@ module.exports = (req, res, next) => co(function *() {
       var unit = req.query.unit == 'relative' ? 'relative' : 'quantitative';
       var massByMembers = req.query.massByMembers == 'no' ? 'no' : 'yes';
       
-      console.log("req.headers.host = %s", req.headers.host);
+      //console.log("req.headers.host = %s", req.headers.host);
       
       res.locals = {
 	host: req.headers.host.toString(),
diff --git a/views/Chart.html b/views/Chart.html
index c5ee51f..231a804 100755
--- a/views/Chart.html
+++ b/views/Chart.html
@@ -6,7 +6,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
     <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
diff --git a/views/about.html b/views/about.html
index b3b5a6d..0c30e3d 100755
--- a/views/about.html
+++ b/views/about.html
@@ -5,7 +5,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
     <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
diff --git a/views/members.html b/views/members.html
index 4760960..b50e576 100755
--- a/views/members.html
+++ b/views/members.html
@@ -5,7 +5,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
     <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
diff --git a/views/willMembers.html b/views/willMembers.html
index 5e3bc1e..a4bf46d 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -5,7 +5,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <!-- <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td> -->
+    <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
     <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-- 
GitLab


From 52362f1d786b0d9395521a18fe49aef4647a1273 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 17:25:48 +0200
Subject: [PATCH 21/48] [willMembers] add membersCount to req get current block

---
 lib/updateCache.js    | 2 +-
 routes/willMembers.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/updateCache.js b/lib/updateCache.js
index 606d28d..eb7d323 100755
--- a/lib/updateCache.js
+++ b/lib/updateCache.js
@@ -401,7 +401,7 @@ module.exports = (req, res, next) => co(function *() {
 	var stmt = db.prepare("INSERT INTO blocks VALUES (?,?,?)");
 	for (let i=0;i<bddBuffer.blocks.length;i++)
 	{
-	  console.log("bddBuffer[%s] = (%s,%s,%s)", i, bddBuffer.blocks[i].number, bddBuffer.blocks[i].time, bddBuffer.blocks[i].newSentries);
+	  //console.log("bddBuffer[%s] = (%s,%s,%s)", i, bddBuffer.blocks[i].number, bddBuffer.blocks[i].time, bddBuffer.blocks[i].newSentries);
 	  sentriesCount += bddBuffer.blocks[i].newSentries;
 	  stmt.run(bddBuffer.blocks[i].number, bddBuffer.blocks[i].time, sentriesCount);
 	}
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 0524fc9..c853a41 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -12,7 +12,7 @@ module.exports = (req, res, next) => co(function *() {
   
   try {
     // get blockchain timestamp
-    let resultQueryCurrentBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime`,`number`,`hash` FROM block ORDER BY `medianTime` DESC LIMIT 1 ');
+    let resultQueryCurrentBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime`,`number`,`hash`,`membersCount` FROM block ORDER BY `medianTime` DESC LIMIT 1 ');
     const currentBlockchainTimestamp = resultQueryCurrentBlock[0].medianTime;
     const currentBlockNumber = resultQueryCurrentBlock[0].number;
     const currentBlockHash = resultQueryCurrentBlock[0].hash;
-- 
GitLab


From 9fee68a0470bc3a19ac1cb6cbe7d4b2ea035158e Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 18:09:24 +0200
Subject: [PATCH 22/48] use duniterServer.home

---
 index.js    | 2 +-
 lib/main.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/index.js b/index.js
index c408d0b..004597f 100755
--- a/index.js
+++ b/index.js
@@ -81,7 +81,7 @@ module.exports = {
       route: (app, server, conf, program, params) => {
         // Main Loop
         //main(server, SERVER_HOST, SERVER_PORT);
-	main(server, null, null, app);  // `app` est un serveur HTTP Express
+	main(server, null, null, app, program);  // `app` est un serveur HTTP Express
 
         // Wait forever, this is a permanent program
         new Promise(() => null);
diff --git a/lib/main.js b/lib/main.js
index 1f194e5..aad5672 100755
--- a/lib/main.js
+++ b/lib/main.js
@@ -13,7 +13,7 @@ const duniter = require(__dirname + '/duniter.js');
 module.exports = (duniterServer, host, port, appParente, program) => co(function *() {
   
   // Create monit database
-  const dbPath = home+'/.config/duniter/'+program.mdb+'/currency-monit.db';
+  const dbPath = duniterServer.home+'/currency-monit.db';
   var db = new sqlite3.Database(dbPath);
   db.serialize(function() {
     db.run("CREATE TABLE if not exists blocks (number TEXT, timestamp TEXT, sentries INT)");
-- 
GitLab


From 252bb366368be3b7e6ff652050f8e0f4bcf655cc Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 18:16:50 +0200
Subject: [PATCH 23/48] change version to module-0.2.3

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index 0c30e3d..58ac606 100755
--- a/views/about.html
+++ b/views/about.html
@@ -28,7 +28,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.2">module-0.2.2</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.3">module-0.2.3</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From b1591e5e9439f5a4b55ce543312503740a98ee24 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 18:33:22 +0200
Subject: [PATCH 24/48] fix bug to lang file call in membersCount route

---
 routes/membersCount.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/routes/membersCount.js b/routes/membersCount.js
index 1e8dad0..49f160c 100755
--- a/routes/membersCount.js
+++ b/routes/membersCount.js
@@ -77,7 +77,7 @@ module.exports = (req, res, next) => co(function *() {
     else
     {
       // get lg file
-      const LANG = getLang(`./lg/membersCount_${req.query.lg||'fr'}.txt`);
+      const LANG = getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`);
       
       // GET parameters
       var unit = req.query.unit == 'relative' ? 'relative' : 'quantitative';
-- 
GitLab


From 56ce590d40fc56105abb1d7b9d3a7b9694c95ba7 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 18:34:31 +0200
Subject: [PATCH 25/48] change version to module-0.2.4

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index 58ac606..5bb0db2 100755
--- a/views/about.html
+++ b/views/about.html
@@ -28,7 +28,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.3">module-0.2.3</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.4">module-0.2.4</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From ca8fe783d5dcf0d7099f8989176017a091a0d35e Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 21:46:58 +0200
Subject: [PATCH 26/48] fix bug in distance rule evaluation

---
 routes/willMembers.js | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/routes/willMembers.js b/routes/willMembers.js
index c853a41..7ed3468 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -212,18 +212,6 @@ module.exports = (req, res, next) => co(function *() {
     }
     else { errors += "<p>ERREUR : param <i>sort_by</i> invalid !</p>"; }
 
-    // Tester la distance à l'aide des certifications disponibles
-    const wotb = duniterServer.dal.wotb.memCopy();
-    const conf = duniterServer.conf
-    const dSen = Math.ceil(Math.pow(resultQueryCurrentBlock[0].membersCount, 1 / conf.stepMax));
-    const pendingIdtyWID = wotb.addNode()
-    for (const cert of idtysPendingCertifsList) {
-      wotb.addLink(cert.wid, pendingIdtyWID)
-    }
-    const isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
-    // Nettoie la wot temporaire
-    wotb.clear();
-
     // Trier les identités par ordre decroissant du critère sort_by
     for (var i=0;i<identitiesList.length;i++)
     {
@@ -249,9 +237,22 @@ module.exports = (req, res, next) => co(function *() {
           { doubloon = true; }
         }
         
-        // Push max value on sort table
+        // Push max value on sort table (and test distance rule)
         if (!doubloon)
         {
+	  // Tester la distance à l'aide des certifications disponibles
+	  const wotb = duniterServer.dal.wotb.memCopy();
+	  const conf = duniterServer.conf
+	  const dSen = Math.ceil(Math.pow(resultQueryCurrentBlock[0].membersCount, 1 / conf.stepMax));
+	  const pendingIdtyWID = wotb.addNode()
+	  for (const cert of idtysPendingCertifsList[idMax])
+	  {
+	    wotb.addLink(cert.wid, pendingIdtyWID)
+	  }
+	  const isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
+	  // Nettoie la wot temporaire
+	  wotb.clear();
+	  
           idtysListOrdered.push({
           uid: identitiesList[idMax].uid,
           creationTimestamp: identitiesList[idMax].creationTimestamp,
-- 
GitLab


From bd8468bfff6fde359eabec7e98bf86b6c152db32 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 21:47:50 +0200
Subject: [PATCH 27/48] change version to module-0.2.5

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index 5bb0db2..9bc9d9b 100755
--- a/views/about.html
+++ b/views/about.html
@@ -28,7 +28,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.4">module-0.2.4</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.5">module-0.2.5</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From c6c38a923a86bdc67489bdc68361221f2cad0a52 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 22:01:17 +0200
Subject: [PATCH 28/48] optimize with calculate dSen once time

---
 routes/willMembers.js | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/routes/willMembers.js b/routes/willMembers.js
index 7ed3468..d66e0e3 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -20,6 +20,10 @@ module.exports = (req, res, next) => co(function *() {
     // Dictionnaire pubkey => wid (wotb ID)
     const widsCache = {}
     
+    // Initaliser les constantes
+    const conf = duniterServer.conf;
+    const dSen = Math.ceil(Math.pow(resultQueryCurrentBlock[0].membersCount, 1 / conf.stepMax));
+    
     // Initaliser les variables
     var errors = "";
     var identitiesList = [];
@@ -241,15 +245,14 @@ module.exports = (req, res, next) => co(function *() {
         if (!doubloon)
         {
 	  // Tester la distance à l'aide des certifications disponibles
-	  const wotb = duniterServer.dal.wotb.memCopy();
-	  const conf = duniterServer.conf
-	  const dSen = Math.ceil(Math.pow(resultQueryCurrentBlock[0].membersCount, 1 / conf.stepMax));
-	  const pendingIdtyWID = wotb.addNode()
+	  let wotb = duniterServer.dal.wotb.memCopy();
+	  
+	  let pendingIdtyWID = wotb.addNode()
 	  for (const cert of idtysPendingCertifsList[idMax])
 	  {
 	    wotb.addLink(cert.wid, pendingIdtyWID)
 	  }
-	  const isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
+	  let isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
 	  // Nettoie la wot temporaire
 	  wotb.clear();
 	  
-- 
GitLab


From 56699088efdbc4966cb07806433aaa0dbd222eb6 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 20 Jun 2017 22:06:38 +0200
Subject: [PATCH 29/48] change version to module-0.2.6

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index 9bc9d9b..7156c98 100755
--- a/views/about.html
+++ b/views/about.html
@@ -28,7 +28,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.5">module-0.2.5</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.6">module-0.2.6</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From 74c28f37adc3a5152d2f3c3637661466051678fb Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Mon, 26 Jun 2017 14:05:26 +0200
Subject: [PATCH 30/48] add currency name at html title

---
 lib/main.js            |  55 +++++++--
 lib/updateCache.js     | 251 +++++++++++++++++++++++++++++------------
 lib/webserver.js       |   1 +
 routes/membersCount.js |   9 +-
 routes/willMembers.js  |  14 +--
 views/Chart.html       |   3 +
 views/HEAD.html        |   5 +-
 views/about.html       |   5 +-
 views/members.html     |   3 +
 views/willMembers.html |   3 +
 10 files changed, 250 insertions(+), 99 deletions(-)

diff --git a/lib/main.js b/lib/main.js
index aad5672..2094bd6 100755
--- a/lib/main.js
+++ b/lib/main.js
@@ -1,7 +1,7 @@
 "use strict";
 
 const co = require('co');
-const sqlite3 = require('sqlite3').verbose();
+//const sqlite3 = require('sqlite3').verbose();
 const home = require('os').homedir();
 
 const webserver = require(__dirname + '/webserver.js');
@@ -12,31 +12,66 @@ const duniter = require(__dirname + '/duniter.js');
  */
 module.exports = (duniterServer, host, port, appParente, program) => co(function *() {
   
-  // Create monit database
-  const dbPath = duniterServer.home+'/currency-monit.db';
-  var db = new sqlite3.Database(dbPath);
-  db.serialize(function() {
-    db.run("CREATE TABLE if not exists blocks (number TEXT, timestamp TEXT, sentries INT)");
-  });
-  db.close();
-  
   // Define cache
   var cache = {
+    lastUptime: 0,
     lock : false,
     beginBlock: null,
     currentBlockNumber : 0,
     currentBlockTime: 0,
+    currentSentries: 0,
     endBlock: null,
     step: null,
     stepUnit: null,
     stepTime: null,
     onlyDate: null,
     Yn: 0,
-    destroyAmount: 0,
     pubkeys: new Array(),
     pub_index: new Array(),
     blockchain: new Array()
   };
+  
+  // Create or open monit database
+  const dbPath = duniterServer.home+'/currency-monit.db';
+  /*var db = new sqlite3.Database(dbPath);
+  db.serialize(function() {
+    db.run("CREATE TABLE if not exists blocks (number TEXT, hash TEXT, medianTime TEXT, sentries INT)");
+    db.run("CREATE TABLE if not exists pubkeys (pub TEXT, expires_on TEXT, writtenCerts TEXT, receivedCerts TEXT)");
+    db.each("SELECT `number`,`hash`,`medianTime`,`sentries` FROM blocks ORDER BY medianTime ASC", function(err, row) {
+        if (err != null) { console.log(err); }
+        else
+	{
+	  let newSentries = row.sentries-cache.currentSentries;
+	  if (newSentries != 0)
+	  {
+	    cache.blockchain.push({
+	      number: row.number,
+	      hash: row.hash,
+	      medianTime: row.medianTime,
+	      newSentries: newSentries,
+	      sentries: row.sentries
+	    });
+	    cache.currentBlockNumber = row.number;
+	    cache.currentBlockTime = row.medianTime;
+	    cache.currentSentries = row.sentries;
+	  }
+	}
+    });
+    db.each("SELECT `pub`,`expires_on`,`writtenCerts`,`receivedCerts` FROM pubkeys", function(err, row) {
+      if (err != null) { console.log(err); }
+      else
+      {
+	cache.pubkeys.push({
+	      updateWot: false,
+	      expires_on: row.expires_on,
+	      pub: row.pub,
+	      writtenCerts: JSON.parse(row.writtenCerts),
+	      receivedCerts: JSON.parse(row.receivedCerts)
+	    });
+      }
+    });
+  });
+  db.close();*/
     
   // Confirm started
   console.log("module currency-monit started");
diff --git a/lib/updateCache.js b/lib/updateCache.js
index eb7d323..25cdf90 100755
--- a/lib/updateCache.js
+++ b/lib/updateCache.js
@@ -1,10 +1,11 @@
 "use strict";
 
 const co = require('co');
-const sqlite3 = require('sqlite3').verbose();
+//const sqlite3 = require('sqlite3').verbose();
 
 const STEP_COUNT_MIN = 4;
 const STEP_COUNT_MAX = 150;
+const MIN_CACHE_UPDATE_FREQ = 150; // 2 min 30 (150 sec)
 
 /**
      * updateCache
@@ -20,21 +21,22 @@ module.exports = (req, res, next) => co(function *() {
 
     // Lock cache
     cache.lock = true;
-    
+
     // If fork, unstack cache
+    let reinitBdd = false;
     if (cache.endBlock != null)
     {
-      let currentBlock = yield duniterServer.dal.peerDAL.query('SELECT `hash` FROM block WHERE `fork`=0 AND `number`='+(cache.blockchain.length-1)+' LIMIT 1 ');
-      if (cache.blockchain.length > 0 && cache.blockchain[cache.blockchain.length-1].hash != currentBlock[0].hash)
+      let checkBlock = yield duniterServer.dal.peerDAL.query('SELECT `hash` FROM block WHERE `fork`=0 AND `number`='+(cache.blockchain[cache.blockchain.length-1].number)+' LIMIT 1 ');
+      if (cache.blockchain.length > 0 && cache.blockchain[cache.blockchain.length-1].hash != checkBlock[0].hash && Math.floor(Date.now() / 1000) > (cache.lastUptime + MIN_CACHE_UPDATE_FREQ))
       {
 	/*// unstack loop
-	while (cache.blockchain.length > 0  && cache.blockchain[cache.blockchain.length-1].hash != currentBlock[0].hash)
+	while (cache.blockchain.length > 0  && cache.blockchain[cache.blockchain.length-1].hash != checkBlock[0].hash)
 	{
 	  // unstack cache.blockchain
 	  cache.blockchain.pop();
 	  
 	  // unstack block
-	  currentBlock = yield duniterServer.dal.peerDAL.query('SELECT `hash` FROM block WHERE `fork`=0 AND `number`='+(cache.blockchain.length-1)+' LIMIT 1 ');
+	  checkBlock = yield duniterServer.dal.peerDAL.query('SELECT `hash` FROM block WHERE `fork`=0 AND `number`='+(cache.blockchain.length-1)+' LIMIT 1 ');
 	  
 	  console.log("unstack block #%s", cache.blockchain.length-1);
 	}
@@ -48,19 +50,25 @@ module.exports = (req, res, next) => co(function *() {
 	{*/
 	  // reinitialize cache
 	  cache = {
+	    lastUptime: 0,
 	    lock : false,
 	    beginBlock: null,
+	    currentBlockNumber : 0,
+	    currentBlockTime: 0,
+	    currentSentries: 0,
 	    endBlock: null,
 	    step: null,
 	    stepUnit: null,
 	    stepTime: null,
 	    onlyDate: null,
 	    Yn: 0,
-	    destroyAmount: 0,
 	    pubkeys: new Array(),
 	    pub_index: new Array(),
 	    blockchain: new Array()
 	  };
+	  
+	  // reinitialize bdd
+	  reinitBdd = true;
 	/*}
 	
 	// unstak pubkeys joins during the fork (no-member pubkeys has considered join when then received currency for the first time)
@@ -142,43 +150,68 @@ module.exports = (req, res, next) => co(function *() {
     { cache.step = Math.ceil((cache.endBlock[0].medianTime-cache.beginBlock[0].medianTime)/(STEP_COUNT_MAX*unitTime)); }
     cache.stepTime = parseInt(cache.step)*unitTime;
 
-    // if new blocks, update cache
-    if ( parseInt(cache.endBlock[0].number) >= cache.currentBlockNumber )
+    // if new blocks and MIN_CACHE_UPDATE_FREQ pass, update cache
+    if ( parseInt(cache.endBlock[0].number) >= cache.currentBlockNumber && Math.floor(Date.now() / 1000) > (cache.lastUptime + MIN_CACHE_UPDATE_FREQ))
     {
       // let previousCacheTime = (cache.blockchain.length > 0) ? cache.blockchain[cache.blockchain.length-1].medianTime:0;
       var newBlocks = yield duniterServer.dal.peerDAL.query(
-	'SELECT `hash`,`membersCount`,`medianTime`,`number`,`dividend`,`transactions`,`joiners`,`certifications`,`issuersCount` FROM block WHERE `fork`=0 AND `medianTime` > '+cache.currentBlockTime+' AND `medianTime` <= '+cache.endBlock[0].medianTime+' ORDER BY `medianTime` ASC');
+	'SELECT `hash`,`membersCount`,`medianTime`,`number`,`certifications`,`joiners`,`actives`,`revoked` FROM block WHERE `fork`=0 AND `medianTime` > '+cache.currentBlockTime+' AND `medianTime` <= '+cache.endBlock[0].medianTime+' ORDER BY `medianTime` ASC');
       
-      if ( cache.currentBlockNumber > 0 && (newBlocks.length-1) != (parseInt(cache.endBlock[0].number)-cache.currentBlockNumber) )
+      /*if ( cache.currentBlockNumber > 0 && (newBlocks.length) != (parseInt(cache.endBlock[0].number)-cache.currentBlockNumber) )
       {
-	res.status(500).send('<pre>Fatal Error : newBlocks.length != (endBlock[0].number-cache.blockchain.length)</pre>');
-      }
+        console.log("newBlocks.length = %s", newBlocks.length);
+	console.log("cache.endBlock[0].number = %s", cache.endBlock[0].number);
+	console.log("cache.currentBlockNumber = %s", cache.currentBlockNumber);
+	res.status(500).send('<pre>Fatal Error : newBlocks.length != (endBlock[0].number-cache.currentBlockNumber)</pre>');
+      }*/
       
-      // Initialise bddBuffer
-      let bddBuffer = {
-	blocks: new Array()
-      };
+      // Initialise newJoiners
+      let newJoiners = new Array();
       
+      // Initialise delIdtys
+      let delIdtys = new Array();
       
       for (let b=0;b<newBlocks.length;b++)
       {
 	// Init let variables
 	let newSentries=0;
-	let transactions = [];
+	let expireCertsNumber=-1;
+	let minReceivedCerts = 0;
+	let revoked = [];
+	let actives = [];
 	let joiners = [];
 	let certifications = [];
 	
+	/*// get expireCertsNumber
+	let tmpExpireCertsBlock = yield duniterServer.dal.peerDAL.query(
+	'SELECT `number` FROM block WHERE `fork`=0 AND `medianTime` > '+cache.currentBlockTime+' AND `medianTime` < '+(parseInt(newBlocks[b].medianTime)-sigValidity)+' ORDER BY `medianTime` DESC LIMIT 1');
+        if (tmpExpireCertsBlock.length > 0) { expireCertsNumber = parseInt(tmpExpireCertsBlock[0].number); }
+        
+        // Suppr expires certs
+        if (expireCertsNumber >= 0)
+	{
+	  for (let m=0;m<cache.pubkeys.length;m++)
+	  {
+	    //..
+	  }
+	}*/
+        
+        // For become sentrie, minReceivedCerts is max between Yn and sigQty
+	minReceivedCerts = (cache.Yn<sigQty) ? sigQty:cache.Yn;
+
 	// If Yn change, suppr sentries that not achieve new Yn value
-	let newYn = Math.ceil(Math.pow(cache.endBlock[0].membersCount, 1/stepMax));
+	let newYn = Math.ceil(Math.pow(newBlocks[b].membersCount, 1/stepMax));
 	if (newYn > cache.Yn)
 	{
 	  for (let m=0;m<cache.pubkeys.length;m++)
 	  {
-	    if (cache.pubkeys[m].writtenCerts.length >= cache.Yn && cache.pubkeys[m].receivedCerts.length >= cache.Yn && cache.pubkeys[m].writtenCerts.length < newYn && cache.pubkeys[m].receivedCerts.length < newYn) { newSentries -= 1; }
+	    if (cache.pubkeys[m].writtenCerts.length >= cache.Yn && cache.pubkeys[m].receivedCerts.length >= minReceivedCerts && cache.pubkeys[m].writtenCerts.length < newYn && cache.pubkeys[m].receivedCerts.length < newYn) { newSentries -= 1; }
 	  }
+	  minReceivedCerts = (newYn<sigQty) ? sigQty:newYn; // recalculate minReceivedCerts
 	}
 	cache.Yn = newYn;
 	
+	/*
 	// add dividend to members balance
 	if (parseInt(newBlocks[b].dividend) > 0)
 	{
@@ -190,7 +223,7 @@ module.exports = (req, res, next) => co(function *() {
 	}
 	
 	// parse and push transactions
-	/*transactions = JSON.parse(newBlocks[b].transactions);
+	transactions = JSON.parse(newBlocks[b].transactions);
 	for (let t=0;t<transactions.length;t++)
 	{
 	  // Calculate inputsSum
@@ -328,6 +361,51 @@ module.exports = (req, res, next) => co(function *() {
 	  }
 	}
 	*/
+
+	// parse and split revoked
+	revoked = JSON.parse(newBlocks[b].revoked);
+	for (let r=0;r<revoked.length;r++)
+	{
+	  revoked[r] = revoked[r].split(":");
+	  delIdtys.push(revoked[r][0]);
+	  let tmpPubIndex = cache.pub_index[revoked[r][0]];
+	  /*// Suppr receivers of writtenCerts
+	  for (let wc=0;wc<cache.pubkeys[tmpPubIndex].writtenCerts.length;wc++)
+	  {
+	    let tmpPubIndex2 = cache.pub_index[cache.pubkeys[tmpPubIndex].writtenCerts[wc][1]];
+	    for (let wc2=0;wc2<cache.pubkeys[tmpPubIndex2].receivedCerts.length;wc2++)
+	    {
+	      if ( cache.pubkeys[tmpPubIndex2].receivedCerts[wc2][1] == revoked[r][0] )
+	      {
+		cache.pubkeys[tmpPubIndex2].receivedCerts.splice(wc2,1);
+		wc2 = cache.pubkeys[tmpPubIndex2].receivedCerts.length;
+	      }
+	    }
+	  }
+	  // Suppr issuers of receivedCerts
+	  for (let rc=0;rc<cache.pubkeys[tmpPubIndex].receivedCerts.length;rc++)
+	  {
+	    let tmpPubIndex2 = cache.pub_index[cache.pubkeys[tmpPubIndex].receivedCerts[rc][1]];
+	    for (let rc2=0;rc2<cache.pubkeys[tmpPubIndex2].writtenCerts.length;rc2++)
+	    {
+	      if ( cache.pubkeys[tmpPubIndex2].writtenCerts[rc2][1] == revoked[r][0] )
+	      {
+		cache.pubkeys[tmpPubIndex2].writtenCerts.splice(rc2,1);
+		rc2 = cache.pubkeys[tmpPubIndex2].writtenCerts.length;
+	      }
+	    }
+	  }*/
+	  cache.pubkeys.splice(tmpPubIndex,1);
+	}
+
+	// parse and split actives
+	actives = JSON.parse(newBlocks[b].actives);
+	for (let a=0;a<actives.length;a++)
+	{
+	  actives[a] = actives[a].split(":");
+	  cache.pubkeys[cache.pub_index[actives[a][0]]].expires_on = newBlocks[b].medianTime+msValidity;
+	}
+
 	// parse and split joiners
 	joiners = JSON.parse(newBlocks[b].joiners);
 	for (let j=0;j<joiners.length;j++)
@@ -335,88 +413,113 @@ module.exports = (req, res, next) => co(function *() {
 	  joiners[j] = joiners[j].split(":");
 	  if ( typeof(cache.pub_index[joiners[j][0]]) != 'undefined') 
 	  {
-	    let pubkeyId = cache.pub_index[joiners[j][0]];
-	    cache.pubkeys[pubkeyId].writtenCerts = new Array();
-	    cache.pubkeys[pubkeyId].receivedCerts = new Array();
+	    let tmpPubkeyIndex = cache.pub_index[joiners[j][0]];
+	    cache.pubkeys[tmpPubkeyIndex].updateWot = true;
+	    cache.pubkeys[tmpPubkeyIndex].expires_on = newBlocks[b].medianTime+msValidity;
 	  }
 	  else
 	  {
 	    cache.pubkeys.push({
-	      join: cache.blockchain.length+1,
+	      updateWot: false,
+	      expires_on: newBlocks[b].medianTime+msValidity,
 	      pub: joiners[j][0],
-	      balance: 0,
-	      balanceWithOthers: new Array(),
-	      pubkeyBalanceWithOthers: new Array(),
-	      inputsTime: new Array(),
-	      inputsAmount: new Array(),
-	      outputsTime: new Array(),
-	      outputsAmount: new Array(),
-	      writtenCerts: new Array(), // tab of blocks number (only for members pubkeys)
-	      receivedCerts: new Array() // tab of blocks number (only for members pubkeys)
+	      writtenCerts: new Array(),
+	      receivedCerts: new Array()       
 	    });
 	    cache.pub_index[joiners[j][0]] = cache.pubkeys.length-1;
+	    newJoiners.push(joiners[j][0]);
 	  }
 	}
-	
+
 	// parse and split certifications
 	certifications = JSON.parse(newBlocks[b].certifications);
 	for (let c=0;c<certifications.length;c++)
 	{
 	  certifications[c] = certifications[c].split(":");
-	  cache.pubkeys[cache.pub_index[certifications[c][0]]].writtenCerts.push(cache.blockchain.length+1);
-	  cache.pubkeys[cache.pub_index[certifications[c][1]]].receivedCerts.push(cache.blockchain.length+1);
-	  if (cache.pubkeys[cache.pub_index[certifications[c][0]]].writtenCerts.length == cache.Yn && cache.pubkeys[cache.pub_index[certifications[c][0]]].receivedCerts.length >= cache.Yn) { newSentries++; }
-	  if (cache.pubkeys[cache.pub_index[certifications[c][1]]].writtenCerts.length >= cache.Yn && cache.pubkeys[cache.pub_index[certifications[c][1]]].receivedCerts.length == cache.Yn) { newSentries++; }
+	  // push cert to cache
+	  cache.pubkeys[cache.pub_index[certifications[c][0]]].writtenCerts.push(certifications[c][2]);
+	  cache.pubkeys[cache.pub_index[certifications[c][0]]].updateWot = true;
+	  cache.pubkeys[cache.pub_index[certifications[c][1]]].receivedCerts.push(certifications[c][2]);
+	  cache.pubkeys[cache.pub_index[certifications[c][1]]].updateWot = true;
+	  
+	  // Calculate if the issuer of cert become sentry
+	  if (cache.pubkeys[cache.pub_index[certifications[c][0]]].writtenCerts.length == cache.Yn && cache.pubkeys[cache.pub_index[certifications[c][0]]].receivedCerts.length >= minReceivedCerts)
+	  { newSentries++; }
+	  
+	  // Calculate if the receiver of cert become sentry
+	  if (cache.pubkeys[cache.pub_index[certifications[c][1]]].writtenCerts.length >= cache.Yn && cache.pubkeys[cache.pub_index[certifications[c][1]]].receivedCerts.length == minReceivedCerts)
+	  { newSentries++; }
 	}
-	
-	// Add block to bddBuffer
-	cache.currentBlockNumber++;
-	cache.currentBlockTime = newBlocks[b].medianTime;
-	if (newSentries > 0)
+
+	if (newSentries != 0)
 	{
-	  bddBuffer.blocks.push({
-	    number: cache.currentBlockNumber,
-	    time: cache.currentBlockTime,
-	    newSentries: newSentries
+	  cache.blockchain.push({
+	    number: newBlocks[b].number,
+	    hash: newBlocks[b].hash,
+	    medianTime: newBlocks[b].medianTime,
+	    newSentries: newSentries,
+	    sentries: (cache.blockchain.length > 0) ? cache.blockchain[cache.blockchain.length-1].sentries+newSentries:newSentries
 	  });
 	}
+      } // end of newBlocks loop
 
-	cache.blockchain.push({
-	  hash: newBlocks[b].hash,
-	  medianTime: newBlocks[b].medianTime,
-	  sentries: (cache.blockchain.length > 0) ? cache.blockchain[cache.blockchain.length-1].sentries+newSentries:newSentries,
-	});
-      }
-      
-      // DEBUG BALANCE
-      //console.log("cache.destroyAmount = %s", cache.destroyAmount);
+      // update cache.currentBlockNumber and cache.currentBlockTime
+      cache.currentBlockNumber = cache.endBlock[0].number;
+      cache.currentBlockTime = cache.endBlock[0].medianTime;
       
-      // Write bddBuffer to currency-monit bdd 
+      /*// Write to currency-monit bdd 
       let db = new sqlite3.Database(dbPath);
       db.serialize(function() {
+	// reinitialize bdd, if it requested
+	if (reinitBdd) { db.exec("TRUNCATE TABLE `blocks`"); db.exec("TRUNCATE TABLE `pubkeys`"); }
+	
 	let sentriesCount = 0;
-	db.all("SELECT sentries FROM blocks ORDER BY timestamp DESC LIMIT 1", function(err, rows) {
-	      if (rows.length > 0) { sentriesCount = rows.sentries; }
+	let indexMedianTime = 0;
+	db.all("SELECT sentries,medianTime FROM blocks ORDER BY medianTime DESC LIMIT 1", function(err, rows) {
+	      if (err != null) { console.log(err); }
+	      else if (rows.length > 0) { sentriesCount = rows[0].sentries; indexMedianTime = rows[0].medianTime; }
 	    });
-	var stmt = db.prepare("INSERT INTO blocks VALUES (?,?,?)");
-	for (let i=0;i<bddBuffer.blocks.length;i++)
+	var stmt = db.prepare("INSERT INTO blocks VALUES (?,?,?,?)");
+	for (let i=0;i<cache.blockchain.length;i++)
 	{
-	  //console.log("bddBuffer[%s] = (%s,%s,%s)", i, bddBuffer.blocks[i].number, bddBuffer.blocks[i].time, bddBuffer.blocks[i].newSentries);
-	  sentriesCount += bddBuffer.blocks[i].newSentries;
-	  stmt.run(bddBuffer.blocks[i].number, bddBuffer.blocks[i].time, sentriesCount);
+	  sentriesCount += cache.blockchain[i].newSentries;
+	  if (cache.blockchain[i].newSentries != 0 && cache.blockchain[i].medianTime > indexMedianTime) { stmt.run(cache.blockchain[i].number, cache.blockchain[i].hash, cache.blockchain[i].medianTime, sentriesCount); }
 	}
 	stmt.finalize();
-	  
-	    /*db.each("SELECT number, timestamp, sentries FROM blocks", function(err, row) {
-		console.log("#" + row.number + ":" + row.timestamp + ":" + row.sentries);
-	    });*/
+	// Delete revoked pubkeys
+	var req_del_pubkeys = db.prepare("DELETE FROM pubkeys WHERE `pub` = ?");
+	for (let i=0;i<delIdtys.length;i++) { req_del_pubkeys.run(delIdtys[i]); }
+	req_del_pubkeys.finalize();
+	// Update no-new pubkeys
+	for (let i=0;i<cache.pubkeys.length;i++)
+	{
+	  // Update writtenCerts and receivedCerts
+	  if (cache.pubkeys[i].updateWot)
+	  {
+	    db.exec("UPDATE `pubkeys` SET `writtenCerts` = '"+JSON.stringify(cache.pubkeys[i].writtenCerts)
+	      +"', `receivedCerts` = '"+JSON.stringify(cache.pubkeys[i].receivedCerts)
+	      +"' WHERE `pub` = '"+cache.pubkeys[i].pub+"'");
+	  }
+	}
+	// Insert new pubkeys
+	var req_insert_pubkeys = db.prepare("INSERT INTO pubkeys VALUES (?,?,?,?)");
+	for (let i=0;i<newJoiners.length;i++)
+	{
+	  let pubIndex = cache.pub_index[newJoiners[i]];
+	  req_insert_pubkeys.run(newJoiners[i], cache.pubkeys[pubIndex].expires_on,
+		JSON.stringify(cache.pubkeys[pubIndex].writtenCerts), JSON.stringify(cache.pubkeys[pubIndex].receivedCerts));
+	}
+	req_insert_pubkeys.finalize();
       });
-      db.close();
+      db.close();*/
+      
+      // Upgrade lastUptime
+      cache.lastUptime = Math.floor(Date.now() / 1000);
     }
-    
-    // Unlock cache
-    cache.lock = false;
-    
+
+      // Unlock cache
+      cache.lock = false;
+
     next()
   } catch (e) {
     // En cas d'exception, afficher le message
diff --git a/lib/webserver.js b/lib/webserver.js
index c7d945c..58199da 100755
--- a/lib/webserver.js
+++ b/lib/webserver.js
@@ -39,6 +39,7 @@ module.exports = (host, port, appParente, duniterServer, cache, dbPath) => {
   app.set('view engine', 'html') // register the template engine
   
   app.locals.duniterServer = duniterServer
+  app.locals.currencyName = duniterServer.conf.currency
   app.locals.sigValidity = duniterServer.conf.sigValidity
   app.locals.msValidity = duniterServer.conf.msValidity
   app.locals.sigWindow = duniterServer.conf.sigWindow
diff --git a/routes/membersCount.js b/routes/membersCount.js
index 49f160c..cfacf97 100755
--- a/routes/membersCount.js
+++ b/routes/membersCount.js
@@ -31,17 +31,20 @@ module.exports = (req, res, next) => co(function *() {
       if ( Math.ceil((cache.endBlock[0].number-cache.beginBlock[0].number)/cache.step) > STEP_COUNT_MAX  ) { cache.step = Math.ceil((cache.endBlock[0].number-cache.beginBlock[0].number)/STEP_COUNT_MAX); }
     }
     
-    // Initialize nextStepTimen, stepIssuerCount and bStep
+    // Initialize nextStepTime, stepIssuerCount and bStep
     var nextStepTime = blockchain[0].medianTime;
     let stepIssuerCount = 0;
     let bStep = 0;
 
     // fill tabMembersCount
     var tabMembersCount = [];
+    let cacheIndex = 0;
     for (let b=0;b<blockchain.length;b++)
     {
       stepIssuerCount += blockchain[b].issuersCount;
       bStep++;
+      
+      while (cacheIndex < (cache.blockchain.length-1) && cache.blockchain[cacheIndex+1].number <= b) { cacheIndex++; }
 
       // If achieve next step
       if ( (cache.stepUnit == "blocks" && bStep == cache.step) || (cache.stepUnit != "blocks" && blockchain[b].medianTime >= nextStepTime))
@@ -52,7 +55,7 @@ module.exports = (req, res, next) => co(function *() {
 	    timestamp: blockchain[b].medianTime,
 	    dateTime: timestampToDatetime(blockchain[b].medianTime),
 	    membersCount: blockchain[b].membersCount,
-	    sentriesCount: cache.blockchain[parseInt(cache.beginBlock[0].number)+b].sentries,
+	    sentriesCount: cache.blockchain[cacheIndex].sentries,
 	    issuersCount: parseInt(stepIssuerCount/bStep)
 	});
 	  
@@ -68,7 +71,7 @@ module.exports = (req, res, next) => co(function *() {
 	    timestamp: blockchain[blockchain.length-1].medianTime,
 	    dateTime: timestampToDatetime(blockchain[blockchain.length-1].medianTime),
 	    membersCount: blockchain[blockchain.length-1].membersCount,
-	    sentriesCount: cache.blockchain[parseInt(cache.beginBlock[0].number)+blockchain.length-1].sentries,
+	    sentriesCount: cache.blockchain[cache.blockchain.length-1].sentries,
 	    issuersCount: blockchain[blockchain.length-1].issuersCount
 	  });
     
diff --git a/routes/willMembers.js b/routes/willMembers.js
index d66e0e3..1b194c6 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -82,11 +82,11 @@ module.exports = (req, res, next) => co(function *() {
 	  if ( tmpQueryGetUidIssuerPendingCert.length > 0 )
 	  {
 	    // Mémoriser le wid
-      const pubkeyFrom = tmpQueryPendingCertifsList[j].from
-      if (!widsCache[pubkeyFrom]) {
-        // Récupère le wotb_id depuis la table d'index globale
-        widsCache[pubkeyFrom] = (yield duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [pubkeyFrom]))[0].wotb_id
-      }
+	    const pubkeyFrom = tmpQueryPendingCertifsList[j].from
+	    if (!widsCache[pubkeyFrom]) {
+	      // Récupère le wotb_id depuis la table d'index globale
+	      widsCache[pubkeyFrom] = (yield duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [pubkeyFrom]))[0].wotb_id
+	    }
 
 	    // Vérifier si le blockstamp est correct
 	    var validBlockStamp = false;
@@ -115,7 +115,7 @@ module.exports = (req, res, next) => co(function *() {
 	      if (tmpQueryPendingCertifsList[j].expires_on > currentBlockchainTimestamp)
 	      {
 		idtysPendingCertifsList[i].push({
-      wid: widsCache[pubkeyFrom],
+		  wid: widsCache[pubkeyFrom],
 		  from: tmpQueryGetUidIssuerPendingCert[0].uid,
 		  pubkey: tmpQueryPendingCertifsList[j].from,
 		  blockNumber: tmpQueryPendingCertifsList[j].block_number,
@@ -246,7 +246,7 @@ module.exports = (req, res, next) => co(function *() {
         {
 	  // Tester la distance à l'aide des certifications disponibles
 	  let wotb = duniterServer.dal.wotb.memCopy();
-	  
+
 	  let pendingIdtyWID = wotb.addNode()
 	  for (const cert of idtysPendingCertifsList[idMax])
 	  {
diff --git a/views/Chart.html b/views/Chart.html
index 231a804..5bc10d7 100755
--- a/views/Chart.html
+++ b/views/Chart.html
@@ -1,4 +1,7 @@
 ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
+  <title>${currencyName}-monit</title>
+</head>
+<body>
 
 <!-- Afficher le menu -->
 <script src=${(host.substr(host.length-6,6) == '.onion') ? "http://722iprlhm7pw4mx7.onion/js/Chart.min.js":"https://librelois.fr/js/Chart.min.js"}></script>
diff --git a/views/HEAD.html b/views/HEAD.html
index 7166b07..d2dec59 100755
--- a/views/HEAD.html
+++ b/views/HEAD.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <html>
   <head>
-    <title>ğ1-monit</title>
     <link rel="icon" type="image/png" 
           href="https://librelois.fr/public/duniter.ico" />
     <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
@@ -10,6 +9,4 @@
       html, body, *, pre {
         font-family: 'Ubuntu';
       }
-    </style>
-  </head>
-  <body>
\ No newline at end of file
+    </style>
\ No newline at end of file
diff --git a/views/about.html b/views/about.html
index 7156c98..d73f360 100755
--- a/views/about.html
+++ b/views/about.html
@@ -1,5 +1,8 @@
 ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
-
+  <title>${currencyName}-monit</title>
+</head>
+<body>
+  
 <!-- Afficher le menu -->
 <table align="center" width="100%">
   <tr>
diff --git a/views/members.html b/views/members.html
index b50e576..71da73d 100755
--- a/views/members.html
+++ b/views/members.html
@@ -1,4 +1,7 @@
 ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
+  <title>${currencyName}-monit</title>
+</head>
+<body>
 
 <!-- Afficher le menu -->
 <table align="center" width="100%">
diff --git a/views/willMembers.html b/views/willMembers.html
index f2d8eb5..aa696da 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -1,4 +1,7 @@
 ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
+  <title>${currencyName}-monit</title>
+</head>
+<body>
 
 <!-- Afficher le menu -->
 <table align="center" width="100%">
-- 
GitLab


From 15d56ed823dbb983799d2fb6d55a6125415dde01 Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Tue, 27 Jun 2017 10:46:22 +0200
Subject: [PATCH 31/48] [enh] Add `membership` column

---
 lg/willMembers_en.txt  |  3 +++
 lg/willMembers_fr.txt  |  3 +++
 routes/willMembers.js  | 11 +++++++++++
 views/willMembers.html |  6 +++++-
 4 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/lg/willMembers_en.txt b/lg/willMembers_en.txt
index f888406..34f2383 100755
--- a/lg/willMembers_en.txt
+++ b/lg/willMembers_en.txt
@@ -27,6 +27,9 @@ COL_4_WITH_AVAIlABILITY_SORT List of received certifications (by availability ti
 COL_DISTANCE distance
 COL_DISTANCE_isOutdistanced KO
 COL_DISTANCE_isNotOutdistanced OK
+COL_MEMBERSHIP membership
+COL_MEMBERSHIP_KO KO
+COL_MEMBERSHIP_OK OK
 SIG_PERIOD_OK available
 INVALID_BLOCKSTAMP invalid blockstamp
 LAST_TR1  total
diff --git a/lg/willMembers_fr.txt b/lg/willMembers_fr.txt
index d720a6a..ba39fc2 100755
--- a/lg/willMembers_fr.txt
+++ b/lg/willMembers_fr.txt
@@ -27,6 +27,9 @@ COL_4_WITH_AVAIlABILITY_SORT liste des certifications reçues (par date de dispo
 COL_DISTANCE distance
 COL_DISTANCE_isOutdistanced KO
 COL_DISTANCE_isNotOutdistanced OK
+COL_MEMBERSHIP adhésion
+COL_MEMBERSHIP_KO KO
+COL_MEMBERSHIP_OK OK
 SIG_PERIOD_OK disponible
 INVALID_BLOCKSTAMP blockstamp incorrect
 LAST_TR1  total
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 1b194c6..91dcc2b 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -253,6 +253,16 @@ module.exports = (req, res, next) => co(function *() {
 	    wotb.addLink(cert.wid, pendingIdtyWID)
 	  }
 	  let isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
+
+    // Tester la présence de l'adhésion
+    let membership = null
+    const pendingMembershipsOfIdty = yield duniterServer.dal.msDAL.getPendingINOfTarget(identitiesList[idMax].hash)
+    for (const ms of pendingMembershipsOfIdty) {
+      if (!membership && ms.expires_on > currentBlockchainTimestamp) {
+        membership = ms
+      }
+    }
+
 	  // Nettoie la wot temporaire
 	  wotb.clear();
 	  
@@ -264,6 +274,7 @@ module.exports = (req, res, next) => co(function *() {
           expires_on: identitiesList[idMax].expires_on,
           nbValidPendingCert: identitiesList[idMax].nbValidPendingCert,
           isOutdistanced,
+          membership: membership,
           pendingCertifications: idtysPendingCertifsList[idMax]
           });
         }
diff --git a/views/willMembers.html b/views/willMembers.html
index aa696da..9b8c36b 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -64,7 +64,8 @@ ${(help != 'no') ? `
   <!-- Printer les nom des colonnes-->
   <tr>
     <td align='center'>${LANG['COL_1']}</td><td align='center'>${LANG['COL_2']}</td>
-    <td align='center'>${LANG['COL_3']}</td><td align='center'>${LANG['COL_DISTANCE']}</td><td style="background:#000000">-</td>
+    <td align='center'>${LANG['COL_3']}</td><td align='center'>${LANG['COL_DISTANCE']}</td>
+    <td align='center'>${LANG['COL_MEMBERSHIP']}</td><td style="background:#000000">-</td>
     <td align='center' colspan="${nbMaxCertifs}">${sortSig == "Availability" 
                                                   ? LANG['COL_4_WITH_AVAIlABILITY_SORT']
                                                   : LANG['COL_4']}</td>
@@ -89,6 +90,9 @@ ${(help != 'no') ? `
         <td align='center' style="background:${idty.colorPending}">
           <span style="color: ${idty.isOutdistanced ? 'red' : 'green' }">${idty.isOutdistanced ? LANG['COL_DISTANCE_isOutdistanced'] : LANG['COL_DISTANCE_isNotOutdistanced'] }</span>
         </td>
+        <td align='center' style="background:${idty.colorPending}">
+          <span style="color: ${idty.membership ? 'green' : 'red' }">${idty.membersip? LANG['COL_MEMBERSHIP_OK'] : LANG['COL_MEMBERSHIP_KO'] }</span>
+        </td>
         <td style="background:#000000">-</td>
         
         <!--printer les certifications-->
-- 
GitLab


From 498ab00b2f9e78e793d24713a2bfa91c07b91621 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 27 Jun 2017 17:38:44 +0200
Subject: [PATCH 32/48] [mod] add cache for willMembers page

---
 routes/willMembers.js | 464 +++++++++++++++++++++---------------------
 1 file changed, 237 insertions(+), 227 deletions(-)

diff --git a/routes/willMembers.js b/routes/willMembers.js
index 91dcc2b..83d2e33 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -4,7 +4,13 @@ const co = require('co')
 const crypto = require('crypto');
 const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
+const MIN_WILLMEMBERS_UPDATE_FREQ = 150;
+
 // Préserver les résultats en cache
+var idtysListOrdered  = [];
+var nbMaxCertifs = 0;
+var countMembersWithSigQtyValidCert = 0;
+var lastUpgradeTime = 0;
 
 module.exports = (req, res, next) => co(function *() {
   
@@ -28,8 +34,6 @@ module.exports = (req, res, next) => co(function *() {
     var errors = "";
     var identitiesList = [];
     var idtysPendingCertifsList = [];
-    var nbMaxCertifs = 0;
-    var countMembersWithSigQtyValidCert = 0;
     
     // Récupérer les paramètres
     var days = req.query.d || 65 // Valeur par défaut
@@ -39,260 +43,266 @@ module.exports = (req, res, next) => co(function *() {
     var sortSig = req.query.sortSig || "Availability"; // Valeur par défaut
     var format = req.query.format || 'HTML';
     
-    // Récupérer la liste des identités en piscine
-    const resultQueryIdtys = yield duniterServer.dal.peerDAL.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on` FROM identities_pending WHERE `member`=0');
-      
-    // Récupérer pour chaque identité, l'ensemble des certifications qu'elle à reçue.
-    for (let i=0;i<resultQueryIdtys.length;i++)
+    // Calculer le timestamp limite à prendre en compte
+    var limitTimestamp = currentBlockchainTimestamp + (days*86400);
+    
+    if (Math.floor(Date.now() / 1000) > (lastUpgradeTime + MIN_WILLMEMBERS_UPDATE_FREQ))
     {
-      // Extraire le numéro de bloc d'émission de l'identité
-      let idtyBlockStamp = resultQueryIdtys[i].buid.split("-");
-      let idtyBlockNumber = idtyBlockStamp[0];
-      
-      // récupérer le medianTime du bloc d'émission de l'identité
-      let resultQueryTimeCreateIdty = yield duniterServer.dal.peerDAL.query('SELECT `medianTime` FROM block WHERE `number`=\''+idtyBlockNumber+'\' LIMIT 1');
-
-	// Stocker les informations de l'identité
-	identitiesList.push({
-	    BlockNumber: idtyBlockNumber,
-	    creationTimestamp: resultQueryTimeCreateIdty[0].medianTime,
-	    pubkey: resultQueryIdtys[i].pubkey,
-	    uid: resultQueryIdtys[i].uid,
-	    hash: resultQueryIdtys[i].hash,
-	    expires_on: resultQueryIdtys[i].expires_on,
-	    nbCert: 0,
-	    nbValidPendingCert: 0,
-	    registrationAvailability: 0
-	});
-	idtysPendingCertifsList.push(new Array());
+      // Réinitialiser le cache
+      idtysListOrdered  = [];
+      nbMaxCertifs = 0;
+      countMembersWithSigQtyValidCert = 0;
+      lastUpgradeTime = Math.floor(Date.now() / 1000);
       
-      // récupérer l'ensemble des certifications en attente destinées à l'identité courante
-      let tmpQueryPendingCertifsList = yield duniterServer.dal.peerDAL.query(
-	'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+resultQueryIdtys[i].pubkey+'\' AND `target`=\''+resultQueryIdtys[i].hash+'\' ORDER BY `expires_on` DESC');
-
-      // Récupérer les uid des émetteurs des certifications reçus par l'utilisateur
-      // Et stocker les uid et dates d'expiration dans un tableau
-      for (let j=0;j<tmpQueryPendingCertifsList.length;j++)
+      // Récupérer la liste des identités en piscine
+      const resultQueryIdtys = yield duniterServer.dal.peerDAL.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on` FROM identities_pending WHERE `member`=0');
+	
+      // Récupérer pour chaque identité, l'ensemble des certifications qu'elle à reçue.
+      for (let i=0;i<resultQueryIdtys.length;i++)
       {
-        // Récupérer le medianTime et le hash du bloc d'émission de la certification 
-	let emittedBlock = yield duniterServer.dal.peerDAL.query('SELECT `hash`,`medianTime` FROM block WHERE `number`=\''+tmpQueryPendingCertifsList[j].block_number+'\' AND `fork`=0 LIMIT 1');
-	  
-	  // Vérifier que l'émetteur de la certification correspond à une identité inscrite en blockchain
-	  let tmpQueryGetUidIssuerPendingCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpQueryPendingCertifsList[j].from+'\' LIMIT 1');
-	  if ( tmpQueryGetUidIssuerPendingCert.length > 0 )
-	  {
-	    // Mémoriser le wid
-	    const pubkeyFrom = tmpQueryPendingCertifsList[j].from
-	    if (!widsCache[pubkeyFrom]) {
-	      // Récupère le wotb_id depuis la table d'index globale
-	      widsCache[pubkeyFrom] = (yield duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [pubkeyFrom]))[0].wotb_id
-	    }
+	// Extraire le numéro de bloc d'émission de l'identité
+	let idtyBlockStamp = resultQueryIdtys[i].buid.split("-");
+	let idtyBlockNumber = idtyBlockStamp[0];
+	
+	// récupérer le medianTime du bloc d'émission de l'identité
+	let resultQueryTimeCreateIdty = yield duniterServer.dal.peerDAL.query('SELECT `medianTime` FROM block WHERE `number`=\''+idtyBlockNumber+'\' LIMIT 1');
 
-	    // Vérifier si le blockstamp est correct
-	    var validBlockStamp = false;
-	    if (emittedBlock[0].hash == tmpQueryPendingCertifsList[j].block_hash)
-	    { validBlockStamp = true; }
-	    
-	    // récupérer le timestamp d'enchainement de la dernière certification écrite par l'émetteur
-	    let tmpQueryLastIssuerCert = yield duniterServer.dal.peerDAL.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+tmpQueryPendingCertifsList[j].from+'\' ORDER BY `chainable_on` DESC LIMIT 1');
-	    let certTimestampWritable = 0;
-	    if ( typeof(tmpQueryLastIssuerCert[0]) != 'undefined' && typeof(tmpQueryLastIssuerCert[0].chainable_on) != 'undefined' )
-	    { certTimestampWritable = tmpQueryLastIssuerCert[0].chainable_on; }
-	    identitiesList[i].registrationAvailability = (certTimestampWritable > identitiesList[i].registrationAvailability) ? certTimestampWritable : identitiesList[i].registrationAvailability;
+	  // Stocker les informations de l'identité
+	  identitiesList.push({
+	      BlockNumber: idtyBlockNumber,
+	      creationTimestamp: resultQueryTimeCreateIdty[0].medianTime,
+	      pubkey: resultQueryIdtys[i].pubkey,
+	      uid: resultQueryIdtys[i].uid,
+	      hash: resultQueryIdtys[i].hash,
+	      expires_on: resultQueryIdtys[i].expires_on,
+	      nbCert: 0,
+	      nbValidPendingCert: 0,
+	      registrationAvailability: 0
+	  });
+	  idtysPendingCertifsList.push(new Array());
+	
+	// récupérer l'ensemble des certifications en attente destinées à l'identité courante
+	let tmpQueryPendingCertifsList = yield duniterServer.dal.peerDAL.query(
+	  'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+resultQueryIdtys[i].pubkey+'\' AND `target`=\''+resultQueryIdtys[i].hash+'\' ORDER BY `expires_on` DESC');
+
+	// Récupérer les uid des émetteurs des certifications reçus par l'utilisateur
+	// Et stocker les uid et dates d'expiration dans un tableau
+	for (let j=0;j<tmpQueryPendingCertifsList.length;j++)
+	{
+	  // Récupérer le medianTime et le hash du bloc d'émission de la certification 
+	  let emittedBlock = yield duniterServer.dal.peerDAL.query('SELECT `hash`,`medianTime` FROM block WHERE `number`=\''+tmpQueryPendingCertifsList[j].block_number+'\' AND `fork`=0 LIMIT 1');
 	    
-	    // Vérifier que l'identité courant n'a pas déjà reçu d'autre(s) certification(s) de la part du même membre ET dans le même état de validité du blockstamp
-	    let doubloonPendingCertif = false;
-	    for (const pendingCert of idtysPendingCertifsList[i])
+	    // Vérifier que l'émetteur de la certification correspond à une identité inscrite en blockchain
+	    let tmpQueryGetUidIssuerPendingCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpQueryPendingCertifsList[j].from+'\' LIMIT 1');
+	    if ( tmpQueryGetUidIssuerPendingCert.length > 0 )
 	    {
-	      if (pendingCert.from == tmpQueryGetUidIssuerPendingCert[0].uid && pendingCert.validBlockStamp == validBlockStamp)
+	      // Mémoriser le wid
+	      const pubkeyFrom = tmpQueryPendingCertifsList[j].from
+	      if (!widsCache[pubkeyFrom]) {
+		// Récupère le wotb_id depuis la table d'index globale
+		widsCache[pubkeyFrom] = (yield duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [pubkeyFrom]))[0].wotb_id
+	      }
+
+	      // Vérifier si le blockstamp est correct
+	      var validBlockStamp = false;
+	      if (emittedBlock[0].hash == tmpQueryPendingCertifsList[j].block_hash)
+	      { validBlockStamp = true; }
+	      
+	      // récupérer le timestamp d'enchainement de la dernière certification écrite par l'émetteur
+	      let tmpQueryLastIssuerCert = yield duniterServer.dal.peerDAL.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+tmpQueryPendingCertifsList[j].from+'\' ORDER BY `chainable_on` DESC LIMIT 1');
+	      let certTimestampWritable = 0;
+	      if ( typeof(tmpQueryLastIssuerCert[0]) != 'undefined' && typeof(tmpQueryLastIssuerCert[0].chainable_on) != 'undefined' )
+	      { certTimestampWritable = tmpQueryLastIssuerCert[0].chainable_on; }
+	      identitiesList[i].registrationAvailability = (certTimestampWritable > identitiesList[i].registrationAvailability) ? certTimestampWritable : identitiesList[i].registrationAvailability;
+	      
+	      // Vérifier que l'identité courant n'a pas déjà reçu d'autre(s) certification(s) de la part du même membre ET dans le même état de validité du blockstamp
+	      let doubloonPendingCertif = false;
+	      for (const pendingCert of idtysPendingCertifsList[i])
 	      {
-		doubloonPendingCertif = true;
+		if (pendingCert.from == tmpQueryGetUidIssuerPendingCert[0].uid && pendingCert.validBlockStamp == validBlockStamp)
+		{
+		  doubloonPendingCertif = true;
+		}
+	      }
+	      if (!doubloonPendingCertif)
+	      {
+		// Stoker la liste des certifications en piscine qui n'ont pas encore expirées
+		if (tmpQueryPendingCertifsList[j].expires_on > currentBlockchainTimestamp)
+		{
+		  idtysPendingCertifsList[i].push({
+		    wid: widsCache[pubkeyFrom],
+		    from: tmpQueryGetUidIssuerPendingCert[0].uid,
+		    pubkey: tmpQueryPendingCertifsList[j].from,
+		    blockNumber: tmpQueryPendingCertifsList[j].block_number,
+		    timestampExpire: tmpQueryPendingCertifsList[j].expires_on,
+		    timestampWritable: certTimestampWritable,
+		    validBlockStamp: validBlockStamp
+		  });
+		  identitiesList[i].nbCert++;
+		  if (validBlockStamp) { identitiesList[i].nbValidPendingCert++; }
+		}
 	      }
 	    }
-	    if (!doubloonPendingCertif)
+	}
+
+	// Calculer le nombre maximal de certifications reçues par l'identité courante
+	if ( identitiesList[i].nbCert > nbMaxCertifs) { nbMaxCertifs = identitiesList[i].nbCert; }
+	
+	// calculate countMembersWithSigQtyValidCert
+	if ( identitiesList[i].nbValidPendingCert >= sigQty) { countMembersWithSigQtyValidCert++; }
+      }
+
+      // Si demandé, retrier les, certifications par date de disponibilité
+      if (sortSig == "Availability")
+      {
+	var idtysPendingCertifsListSort = [ [] ];
+	for (var i=0;i<idtysPendingCertifsList.length;i++)
+	{
+	  idtysPendingCertifsListSort[i] = Array();
+	  let min;
+	  let idMin =0;
+	  let tmpExcluded = Array();
+	  for (let j=0;j<idtysPendingCertifsList[i].length;j++) { tmpExcluded[j] = false; }
+	  for (let j=0;j<idtysPendingCertifsList[i].length;j++)
+	  {
+	    min = currentBlockchainTimestamp+sigValidity; // begin to min = max
+	    
+	    // search idMin (id of certif with min timestampWritable)
+	    for (let k=0;k<idtysPendingCertifsList[i].length;k++)
 	    {
-	      // Stoker la liste des certifications en piscine qui n'ont pas encore expirées
-	      if (tmpQueryPendingCertifsList[j].expires_on > currentBlockchainTimestamp)
+	      if (idtysPendingCertifsList[i][k].timestampWritable < min && !tmpExcluded[k])
 	      {
-		idtysPendingCertifsList[i].push({
-		  wid: widsCache[pubkeyFrom],
-		  from: tmpQueryGetUidIssuerPendingCert[0].uid,
-		  pubkey: tmpQueryPendingCertifsList[j].from,
-		  blockNumber: tmpQueryPendingCertifsList[j].block_number,
-		  timestampExpire: tmpQueryPendingCertifsList[j].expires_on,
-		  timestampWritable: certTimestampWritable,
-		  validBlockStamp: validBlockStamp
-		});
-		identitiesList[i].nbCert++;
-		if (validBlockStamp) { identitiesList[i].nbValidPendingCert++; }
+		min = idtysPendingCertifsList[i][k].timestampWritable;
+		idMin = k;
 	      }
 	    }
+	  
+	    // Push min value on sort table
+	    idtysPendingCertifsListSort[i].push({
+	      wid: idtysPendingCertifsList[i][idMin].wid,
+	      from: idtysPendingCertifsList[i][idMin].from,
+	      blockNumber: idtysPendingCertifsList[i][idMin].blockNumber,
+	      timestampExpire: idtysPendingCertifsList[i][idMin].timestampExpire,
+	      timestampWritable: idtysPendingCertifsList[i][idMin].timestampWritable,
+	      validBlockStamp: idtysPendingCertifsList[i][idMin].validBlockStamp
+	    });
+	
+	    // Exclure la valeur min avant de poursuivre le tri
+	    tmpExcluded[idMin] = true;
 	  }
+	}
+	idtysPendingCertifsList = idtysPendingCertifsListSort;
       }
-
-      // Calculer le nombre maximal de certifications reçues par l'identité courante
-      if ( identitiesList[i].nbCert > nbMaxCertifs) { nbMaxCertifs = identitiesList[i].nbCert; }
       
-      // calculate countMembersWithSigQtyValidCert
-      if ( identitiesList[i].nbValidPendingCert >= sigQty) { countMembersWithSigQtyValidCert++; }
-    }
-
-    // Si demandé, retrier les, certifications par date de disponibilité
-    if (sortSig == "Availability")
-    {
-      var idtysPendingCertifsListSort = [ [] ];
-      for (var i=0;i<idtysPendingCertifsList.length;i++)
+      // Récupérer la valeur du critère de tri pour chaque identité
+      var tabSort = [];
+      if (sort_by == "creationIdty")
+      { 
+	for (const idty of identitiesList)
+	{
+	  tabSort.push(idty.expires_on);
+	}
+      }
+      else if (sort_by == "sigCount" || sort_by == "registrationPackage")
       {
-        idtysPendingCertifsListSort[i] = Array();
-        let min;
-        let idMin =0;
-        let tmpExcluded = Array();
-        for (let j=0;j<idtysPendingCertifsList[i].length;j++) { tmpExcluded[j] = false; }
-        for (let j=0;j<idtysPendingCertifsList[i].length;j++)
-        {
-          min = currentBlockchainTimestamp+sigValidity; // begin to min = max
-          
-          // search idMin (id of certif with min timestampWritable)
-          for (let k=0;k<idtysPendingCertifsList[i].length;k++)
-          {
-            if (idtysPendingCertifsList[i][k].timestampWritable < min && !tmpExcluded[k])
-            {
-              min = idtysPendingCertifsList[i][k].timestampWritable;
-              idMin = k;
-            }
-          }
-        
-          // Push min value on sort table
-          idtysPendingCertifsListSort[i].push({
-            wid: idtysPendingCertifsList[i][idMin].wid,
-            from: idtysPendingCertifsList[i][idMin].from,
-            blockNumber: idtysPendingCertifsList[i][idMin].blockNumber,
-            timestampExpire: idtysPendingCertifsList[i][idMin].timestampExpire,
-            timestampWritable: idtysPendingCertifsList[i][idMin].timestampWritable,
-            validBlockStamp: idtysPendingCertifsList[i][idMin].validBlockStamp
-          });
-      
-          // Exclure la valeur min avant de poursuivre le tri
-          tmpExcluded[idMin] = true;
-        }
+	  // idtys loop
+	  for (const idty of identitiesList)
+	  {
+	    // Calculate registrationAvailabilityDelay
+	    let registrationAvailabilityDelay = (idty.registrationAvailability > currentBlockchainTimestamp) ? (idty.registrationAvailability-currentBlockchainTimestamp):0;
+	    
+	    // Trier les identités au dossier complet par durée entre date de disponibilité et date d'expiration maximale théorique (=sigWindow-registrationAvailabilityDelay)
+	    // Attribuer un malus de sigValidity secondes par certification valide (plafonner à sigQty dans le cas de 'registrationPackage') 
+	    if (sort_by == "registrationPackage" && idty.nbValidPendingCert > sigQty)
+	    {
+	      tabSort.push(sigWindow-registrationAvailabilityDelay + (sigValidity*sigQty));
+	    }
+	    else
+	    {
+	      tabSort.push(sigWindow-registrationAvailabilityDelay + (sigValidity*idty.nbValidPendingCert));
+	    }
+	  }
       }
-      idtysPendingCertifsList = idtysPendingCertifsListSort;
-    }
-    
-    // Initialiser le tableau idtysListOrdered
-    var idtysListOrdered = [ [] ];
+      else { errors += "<p>ERREUR : param <i>sort_by</i> invalid !</p>"; }
 
-    // Calculer le timestamp limite à prendre en compte
-    var limitTimestamp = currentBlockchainTimestamp + (days*86400);
-      
-    // Récupérer la valeur du critère de tri pour chaque identité
-    var tabSort = [];
-    if (sort_by == "creationIdty")
-    { 
-      for (const idty of identitiesList)
+      // Trier les identités par ordre decroissant du critère sort_by
+      for (var i=0;i<identitiesList.length;i++)
       {
-	tabSort.push(idty.expires_on);
-      }
-    }
-    else if (sort_by == "sigCount" || sort_by == "registrationPackage")
-    {
-        // idtys loop
-	for (const idty of identitiesList)
-        {
-	  // Calculate registrationAvailabilityDelay
-	  let registrationAvailabilityDelay = (idty.registrationAvailability > currentBlockchainTimestamp) ? (idty.registrationAvailability-currentBlockchainTimestamp):0;
-	  
-	  // Trier les identités au dossier complet par durée entre date de disponibilité et date d'expiration maximale théorique (=sigWindow-registrationAvailabilityDelay)
-	  // Attribuer un malus de sigValidity secondes par certification valide (plafonner à sigQty dans le cas de 'registrationPackage') 
-	  if (sort_by == "registrationPackage" && idty.nbValidPendingCert > sigQty)
+	let max = -1;
+	let idMax =0;
+	for (var j=0;j<identitiesList.length;j++)
+	{
+	  if (tabSort[j] > max)
 	  {
-	    tabSort.push(sigWindow-registrationAvailabilityDelay + (sigValidity*sigQty));
+	    max = tabSort[j];
+	    idMax = j;
 	  }
-	  else
+	}
+	
+	// Push max value on sort table, only if respect days limit
+	if (limitTimestamp > identitiesList[idMax].expires_on)
+	{
+	  // Vérifier que cette identité n'a pas déjà été prise en compte (empecher les doublons)
+	  let doubloon = false;
+	  for (const idty of idtysListOrdered)
 	  {
-	    tabSort.push(sigWindow-registrationAvailabilityDelay + (sigValidity*idty.nbValidPendingCert));
+	    if (identitiesList[idMax].uid == idty.uid && identitiesList[idMax].BlockNumber == idty.BlockNumber)
+	    { doubloon = true; }
 	  }
-        }
-    }
-    else { errors += "<p>ERREUR : param <i>sort_by</i> invalid !</p>"; }
-
-    // Trier les identités par ordre decroissant du critère sort_by
-    for (var i=0;i<identitiesList.length;i++)
-    {
-      let max = -1;
-      let idMax =0;
-      for (var j=0;j<identitiesList.length;j++)
-      {
-        if (tabSort[j] > max)
-        {
-          max = tabSort[j];
-          idMax = j;
-        }
-      }
-      
-      // Push max value on sort table, only if respect days limit
-      if (limitTimestamp > identitiesList[idMax].expires_on)
-      {
-        // Vérifier que cette identité n'a pas déjà été prise en compte (empecher les doublons)
-        let doubloon = false;
-        for (const idty of idtysListOrdered)
-        {
-          if (identitiesList[idMax].uid == idty.uid && identitiesList[idMax].BlockNumber == idty.BlockNumber)
-          { doubloon = true; }
-        }
-        
-        // Push max value on sort table (and test distance rule)
-        if (!doubloon)
-        {
-	  // Tester la distance à l'aide des certifications disponibles
-	  let wotb = duniterServer.dal.wotb.memCopy();
-
-	  let pendingIdtyWID = wotb.addNode()
-	  for (const cert of idtysPendingCertifsList[idMax])
+	  
+	  // Push max value on sort table (and test distance rule)
+	  if (!doubloon)
 	  {
-	    wotb.addLink(cert.wid, pendingIdtyWID)
-	  }
-	  let isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
+	    // Tester la distance à l'aide des certifications disponibles
+	    let wotb = duniterServer.dal.wotb.memCopy();
 
-    // Tester la présence de l'adhésion
-    let membership = null
-    const pendingMembershipsOfIdty = yield duniterServer.dal.msDAL.getPendingINOfTarget(identitiesList[idMax].hash)
-    for (const ms of pendingMembershipsOfIdty) {
-      if (!membership && ms.expires_on > currentBlockchainTimestamp) {
-        membership = ms
-      }
-    }
+	    let pendingIdtyWID = wotb.addNode()
+	    for (const cert of idtysPendingCertifsList[idMax])
+	    {
+	      wotb.addLink(cert.wid, pendingIdtyWID)
+	    }
+	    let isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
 
-	  // Nettoie la wot temporaire
-	  wotb.clear();
-	  
-          idtysListOrdered.push({
-          uid: identitiesList[idMax].uid,
-          creationTimestamp: identitiesList[idMax].creationTimestamp,
-          pubkey: identitiesList[idMax].pubkey,
-          BlockNumber: identitiesList[idMax].BlockNumber,
-          expires_on: identitiesList[idMax].expires_on,
-          nbValidPendingCert: identitiesList[idMax].nbValidPendingCert,
-          isOutdistanced,
-          membership: membership,
-          pendingCertifications: idtysPendingCertifsList[idMax]
-          });
-        }
+	    // Tester la présence de l'adhésion
+	    let membership = null
+	    const pendingMembershipsOfIdty = yield duniterServer.dal.msDAL.getPendingINOfTarget(identitiesList[idMax].hash)
+	    for (const ms of pendingMembershipsOfIdty) {
+	      if (!membership && ms.expires_on > currentBlockchainTimestamp) {
+		membership = ms
+	      }
+	    }
+
+	    // Nettoie la wot temporaire
+	    wotb.clear();
+	    
+	    idtysListOrdered.push({
+	    uid: identitiesList[idMax].uid,
+	    creationTimestamp: identitiesList[idMax].creationTimestamp,
+	    pubkey: identitiesList[idMax].pubkey,
+	    BlockNumber: identitiesList[idMax].BlockNumber,
+	    expires_on: identitiesList[idMax].expires_on,
+	    nbValidPendingCert: identitiesList[idMax].nbValidPendingCert,
+	    isOutdistanced,
+	    membership: membership,
+	    pendingCertifications: idtysPendingCertifsList[idMax]
+	    });
+	  }
+	}
+	// Exclure la valeur max avant de poursuivre le tri
+	tabSort[idMax] = -1;
       }
-      // Exclure la valeur max avant de poursuivre le tri
-      tabSort[idMax] = -1;
-    }
-    
-    // Si ordre croissant demandé, inverser le tableau
-    if (order == 'asc')
-    {
-      var idtysListOrdered2 = [ [] ];
-      let tmpIdtysListOrderedLength = idtysListOrdered.length;
-      for (let i=0;i<tmpIdtysListOrderedLength;i++)
+      
+      // Si ordre croissant demandé, inverser le tableau
+      if (order == 'asc')
       {
-        idtysListOrdered2[i] = idtysListOrdered[tmpIdtysListOrderedLength-i-1];
+	var idtysListOrdered2 = [ [] ];
+	let tmpIdtysListOrderedLength = idtysListOrdered.length;
+	for (let i=0;i<tmpIdtysListOrderedLength;i++)
+	{
+	  idtysListOrdered2[i] = idtysListOrdered[tmpIdtysListOrderedLength-i-1];
+	}
+	idtysListOrdered = idtysListOrdered2;
       }
-      idtysListOrdered = idtysListOrdered2;
     }
     
     // Si le client demande la réponse au format JSON, le faire
@@ -331,7 +341,7 @@ module.exports = (req, res, next) => co(function *() {
         // Calculer la proportion de temps restant avant l'expiration
         color: function( timestamp, idtyWindow, max )
         {
-	  const MIN = 80;
+	  const MIN = 100;
           let proportion = ((timestamp-currentBlockchainTimestamp)*(max-MIN))/idtyWindow;
           proportion = proportion < MIN ? MIN : proportion > max ? max : proportion 
           let hex = parseInt( proportion ).toString(16)
-- 
GitLab


From 2eac32083c04162fe1764c608d62cc6404d03322 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 27 Jun 2017 17:40:49 +0200
Subject: [PATCH 33/48] upgrade to module-0.2.7

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index d73f360..bc64f1b 100755
--- a/views/about.html
+++ b/views/about.html
@@ -31,7 +31,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.6">module-0.2.6</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.7">module-0.2.7</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From 05f050e2790859b58a34946d166bf272a1a46694 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 27 Jun 2017 17:53:04 +0200
Subject: [PATCH 34/48] [fix] bug menu (membersCount link)

---
 views/Chart.html       | 2 +-
 views/about.html       | 2 +-
 views/members.html     | 2 +-
 views/willMembers.html | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/views/Chart.html b/views/Chart.html
index 5bc10d7..9f4d58b 100755
--- a/views/Chart.html
+++ b/views/Chart.html
@@ -9,7 +9,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+    <td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
     <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
diff --git a/views/about.html b/views/about.html
index bc64f1b..887c82c 100755
--- a/views/about.html
+++ b/views/about.html
@@ -8,7 +8,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+    <td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
     <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
diff --git a/views/members.html b/views/members.html
index 71da73d..1b2ea1d 100755
--- a/views/members.html
+++ b/views/members.html
@@ -8,7 +8,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+    <td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
     <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
diff --git a/views/willMembers.html b/views/willMembers.html
index 9b8c36b..3b39e96 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -8,7 +8,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <tr>
     <td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
     <td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
-    <td><a href="/membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+    <td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
     <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
-- 
GitLab


From 7a59df8837bd62b805c81f3db0138c42d6734a5c Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 27 Jun 2017 18:36:29 +0200
Subject: [PATCH 35/48] [fix] monetaryMass : end to long & members count value

---
 routes/monetaryMass.js | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/routes/monetaryMass.js b/routes/monetaryMass.js
index cf5fd5d..096f21b 100755
--- a/routes/monetaryMass.js
+++ b/routes/monetaryMass.js
@@ -15,7 +15,20 @@ module.exports = (req, res, next) => co(function *() {
     
     // get beginBlock and endBlock
     var beginBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime` FROM block WHERE `number` = '+begin+' LIMIT 1');
-    var endBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime` FROM block WHERE `number` = '+end+' LIMIT 1');
+    var endBlock = null;
+    if (end > 0)
+    {
+      endBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime`,`membersCount` FROM block WHERE `number` = '+end+' LIMIT 1');
+      if ( typeof(endBlock[0]) == 'undefined')
+      {
+	endBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime`,`membersCount`,`number` FROM block ORDER BY `medianTime` DESC LIMIT 1');
+	end = endBlock[0].number;
+      }
+    }
+    else
+    {
+      endBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime`,`membersCount` FROM block ORDER BY `medianTime` DESC LIMIT 1');
+    }
     
     // get blockchain
     if (end >= begin && begin >= 1)
@@ -83,14 +96,14 @@ module.exports = (req, res, next) => co(function *() {
       var fullCurrency = "The currency will be full when the money supply by member will be worth <b>"+meanMonetaryMassAtFullCurrency
 	  +" DU</b> (because 1/c * dtReeval/dt = <b>"+meanMonetaryMassAtFullCurrency+" DU</b>)<br>"
 	  +"Currently, 1 DU<sub>"+duniterServer.conf.currency+"</sub> = <b>"+(currentDividend/100)+"</b> "+duniterServer.conf.currency+" and we have <b>"
-	  +tabCurrency[tabCurrency.length-1].membersCount+"</b> members. Thus in full currency we would have a total money supply of <b>"
-	  +(meanMonetaryMassAtFullCurrency*currentDividend*tabCurrency[tabCurrency.length-1].membersCount/100)+"</b> "+duniterServer.conf.currency
+	  +endBlock[0].membersCount+"</b> members. Thus in full currency we would have a total money supply of <b>"
+	  +(meanMonetaryMassAtFullCurrency*currentDividend*endBlock[0].membersCount/100)+"</b> "+duniterServer.conf.currency
 	  +" (<b>"+(meanMonetaryMassAtFullCurrency*currentDividend/100)+"</b> "+duniterServer.conf.currency+"/member)." ;
 	  
       // Define max yAxes
       var maxYAxes = meanMonetaryMassAtFullCurrency;
       if (unit == "quantitative") { maxYAxes = maxYAxes*currentDividend/100; }
-      if (massByMembers == "no") { maxYAxes = maxYAxes*tabCurrency[tabCurrency.length-1].membersCount; }
+      if (massByMembers == "no") { maxYAxes = maxYAxes*endBlock[0].membersCount; }
       
       res.locals = {
 	 host: req.headers.host.toString(),
-- 
GitLab


From 4ad073d787d0a8ebab7e962e9fcda246c6d9093d Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 27 Jun 2017 18:38:00 +0200
Subject: [PATCH 36/48] uograde to module-0.2.8

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index 887c82c..ffedc84 100755
--- a/views/about.html
+++ b/views/about.html
@@ -31,7 +31,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.7">module-0.2.7</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.8">module-0.2.8</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From 69a8ed50d3d861c097c3856c148a8f400a996ef7 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 27 Jun 2017 18:58:17 +0200
Subject: [PATCH 37/48] [fix] bug memberships view

---
 views/willMembers.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/willMembers.html b/views/willMembers.html
index 3b39e96..6b65491 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -91,7 +91,7 @@ ${(help != 'no') ? `
           <span style="color: ${idty.isOutdistanced ? 'red' : 'green' }">${idty.isOutdistanced ? LANG['COL_DISTANCE_isOutdistanced'] : LANG['COL_DISTANCE_isNotOutdistanced'] }</span>
         </td>
         <td align='center' style="background:${idty.colorPending}">
-          <span style="color: ${idty.membership ? 'green' : 'red' }">${idty.membersip? LANG['COL_MEMBERSHIP_OK'] : LANG['COL_MEMBERSHIP_KO'] }</span>
+          <span style="color: ${idty.membership ? 'green' : 'red' }">${idty.membership? LANG['COL_MEMBERSHIP_OK'] : LANG['COL_MEMBERSHIP_KO'] }</span>
         </td>
         <td style="background:#000000">-</td>
         
-- 
GitLab


From 8143b22937b96f357c9fb6da516090999c2a31ec Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 27 Jun 2017 19:00:31 +0200
Subject: [PATCH 38/48] upgrade to version module-0.2.9

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index ffedc84..a3c8482 100755
--- a/views/about.html
+++ b/views/about.html
@@ -31,7 +31,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.8">module-0.2.8</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.9">module-0.2.9</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From 9ff431ddec1d5d84aa571b132c64979c7eebc4b1 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 27 Jun 2017 19:05:54 +0200
Subject: [PATCH 39/48] [fix] background color in willMembers page

---
 routes/willMembers.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/routes/willMembers.js b/routes/willMembers.js
index 83d2e33..55ae20a 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -341,8 +341,8 @@ module.exports = (req, res, next) => co(function *() {
         // Calculer la proportion de temps restant avant l'expiration
         color: function( timestamp, idtyWindow, max )
         {
-	  const MIN = 100;
-          let proportion = ((timestamp-currentBlockchainTimestamp)*(max-MIN))/idtyWindow;
+	  const MIN = 120;
+          let proportion = (((timestamp-currentBlockchainTimestamp)*(max-MIN))/idtyWindow)+MIN;
           proportion = proportion < MIN ? MIN : proportion > max ? max : proportion 
           let hex = parseInt( proportion ).toString(16)
           return `#${hex}${hex}${hex}`
-- 
GitLab


From 591cf3b2e7c89cfae2b7f624ad86b6dde044e6f9 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Thu, 29 Jun 2017 19:34:19 +0200
Subject: [PATCH 40/48] [enh] integrate wotex module in page !

---
 index.js               |  10 +-
 lg/menu_en.txt         |   2 +-
 lg/menu_fr.txt         |   2 +-
 lg/wotex_en.txt        |  15 +++
 lg/wotex_fr.txt        |  15 +++
 package.json           |   2 +-
 routes/index.js        |  10 ++
 routes/wotex.js        | 291 +++++++++++++++++++++++++++++++++++++++++
 views/Chart.html       |   5 +-
 views/HEAD.html        |   4 +-
 views/about.html       |   4 +-
 views/members.html     |   2 +-
 views/willMembers.html |  11 +-
 views/wotex.html       | 173 ++++++++++++++++++++++++
 14 files changed, 521 insertions(+), 25 deletions(-)
 create mode 100755 lg/wotex_en.txt
 create mode 100755 lg/wotex_fr.txt
 create mode 100755 routes/wotex.js
 create mode 100755 views/wotex.html

diff --git a/index.js b/index.js
index 004597f..545f6b1 100755
--- a/index.js
+++ b/index.js
@@ -34,19 +34,11 @@ module.exports = {
 
           // Define duniter-currency-monit parameters namespace
           const obj = conf['duniter-currency-monit'] = conf['duniter-currency-monit'] || {}
-
-          // We override the wotexURL parameter by the one given
-          obj.wotexURL = program.wotexURL || obj.wotexURL
-
-          // Default value
-          if (!obj.wotexURL) {
-            obj.wotexURL = '#!'
-          }
         })
       },
 
       cliOptions: [
-        { value: '--wotexURL <url>', desc: 'URL of Wotex service for UID links on willMembers page'}
+        //{ value: '--wotexURL <url>', desc: 'URL of Wotex service for UID links on willMembers page'}
       ],
 
       cli: [{
diff --git a/lg/menu_en.txt b/lg/menu_en.txt
index 78f71a4..876b5a5 100755
--- a/lg/menu_en.txt
+++ b/lg/menu_en.txt
@@ -4,5 +4,5 @@ MEMBERS members
 MEMBERS_COUNT membersCount
 BLOCK_COUNT blockCount
 MONETARY_MASS monetaryMass
-PUBKEY_BALANCE pubkeyBalance
+WOTEX wotex
 ABOUT about
\ No newline at end of file
diff --git a/lg/menu_fr.txt b/lg/menu_fr.txt
index c195335..244a325 100755
--- a/lg/menu_fr.txt
+++ b/lg/menu_fr.txt
@@ -4,5 +4,5 @@ MEMBERS listes des membres
 MEMBERS_COUNT nombre de membres
 BLOCK_COUNT nombre de blocs
 MONETARY_MASS masse monétaire
-PUBKEY_BALANCE solde d'une clé
+WOTEX wotex
 ABOUT a propos
\ No newline at end of file
diff --git a/lg/wotex_en.txt b/lg/wotex_en.txt
new file mode 100755
index 0000000..d08e5ae
--- /dev/null
+++ b/lg/wotex_en.txt
@@ -0,0 +1,15 @@
+LG en
+TITLE wotb explorer
+TEST_UID Test UID
+CHECKBOX_PENDING_DATA Include sandbox's data
+MODE_W2U See the distance of User from WoT's point of view
+MODE_U2W See the distance of WoT from User's point of view
+LEGEND_TITLE Legend
+LEGEND_BLACK Black: Member
+LEGEND_BLUE Blue: Sentry (= Member + point of control)
+LEGEND_ORANGE Orange: Pending certification/identity
+LEGEND_RED Red: Ex-member
+STEP Step
+MAX MAX
+INFINITY Infinity
+CURRENT_SENTRIES Current sentries
\ No newline at end of file
diff --git a/lg/wotex_fr.txt b/lg/wotex_fr.txt
new file mode 100755
index 0000000..43c3a1d
--- /dev/null
+++ b/lg/wotex_fr.txt
@@ -0,0 +1,15 @@
+LG fr
+TITLE Explorateur de la Toile de Confiance
+TEST_UID Saisir 
+CHECKBOX_PENDING_DATA Inclure les données en piscine
+MODE_W2U Voir la distance des autres identités vers l'identité de référence choisi
+MODE_U2W Voir la distance de l'identité de référence choisi vers les identités
+LEGEND_TITLE Légende
+LEGEND_BLACK Noir : Membre
+LEGEND_BLUE Bleu : Membre référent (= Membre + point de controle)
+LEGEND_ORANGE Orange : Données en piscine
+LEGEND_RED Rouge : Anciens membres
+STEP Distance
+MAX MAX
+INFINITY Distance infinie
+CURRENT_SENTRIES Membres Référents actuels
\ No newline at end of file
diff --git a/package.json b/package.json
index 353d689..392336c 100755
--- a/package.json
+++ b/package.json
@@ -31,6 +31,6 @@
     "duniter-prover": "1.3.x"
   },
   "peerDependencies": {
-    "duniter": "1.3.9"
+    "duniter": "1.3.13"
   }
 }
diff --git a/routes/index.js b/routes/index.js
index 9bcefb5..41be68a 100755
--- a/routes/index.js
+++ b/routes/index.js
@@ -107,6 +107,16 @@ app.get('/monetaryMass', require(__dirname + '/monetaryMass.js'), (req, res)=> r
          })
  )
 
+/***************************************
+* Wotex
+***************************************/
+app.get('/wotex', require(__dirname + '/wotex.js'), (req, res)=> res.render('wotex.html', {
+	    help: req.query.help,
+            MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
+            LANG: getLang(`${__dirname}/../lg/wotex_${req.query.lg||'fr'}.txt`)
+         })
+ )
+
 
 /***************************************
 * Solde d'une clé
diff --git a/routes/wotex.js b/routes/wotex.js
new file mode 100755
index 0000000..5d76847
--- /dev/null
+++ b/routes/wotex.js
@@ -0,0 +1,291 @@
+"use strict";
+
+const _ = require('underscore')
+const co = require('co')
+const getLang = require(__dirname + '/../lib/getLang')
+
+const MAX_STEP_LOOK = 7
+
+module.exports = (req, res, next) => co(function *() {
+  
+  var { duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, cache  } = req.app.locals
+
+    try {
+      // get GET parameters
+      var format = req.query.format || 'HTML';
+      
+      // get lg file
+      const LANG = getLang(`${__dirname}/../lg/wotex_${req.query.lg||'fr'}.txt`);
+      
+      // Trouve les points de contrôle efficacement grâce au module C (nommé "wotb")
+      const wotb = duniterServer.dal.wotb.memCopy();
+      wotb.setMaxCert(100);
+      const head = yield duniterServer.dal.getCurrentBlockOrNull();
+      const membersCount = head ? head.membersCount : 0;
+      let dSen = Math.ceil(Math.pow(membersCount, 1 / duniterServer.conf.stepMax));
+      const dicoIdentites = {};
+      const pointsDeControle = wotb.getSentries(dSen);
+      const sentries = yield pointsDeControle.map((wotb_id) => co(function*() {
+        const identite = (yield duniterServer.dal.idtyDAL.query('SELECT * FROM i_index WHERE wotb_id = ?', [wotb_id]))[0];
+        identite.statusClass = 'isSentry';
+        dicoIdentites[identite.wotb_id] = identite;
+        return identite;
+      }));
+
+      let searchResult = '';
+      if (req.query.to) {
+        let idty;
+        let pos = 0, search = req.query.to;
+        if (req.query.to.match(/(\[|\])/)) {
+          const match = req.query.to.match(/^(.+)(\[\d+\])!?$/);
+          search = match[1];
+          pos = parseInt(match[2].replace(/(\[|\])/g, ''));
+        }
+        let idties = yield duniterServer.dal.idtyDAL.query('' +
+          'SELECT uid, pub, wotb_id FROM i_index WHERE (uid = ? or pub = ?) ' +
+          'UNION ALL ' +
+          'SELECT uid, pubkey as pub, (SELECT NULL) AS wotb_id FROM idty WHERE (uid = ? or pubkey = ?)', [search, search, search, search]);
+        idty = idties[pos];
+        if (!idty) {
+          searchResult = `
+                  <p>UID or public key « ${req.query.to} » is not known in the WoT nor in the sandboxes.</p>
+                `;
+        } else if (!req.query.pending && idty.wotb_id === null) {
+          searchResult = `
+                  <p>UID or public key « ${req.query.to} » requires the "Include sandbox's data" option to be enabled.</p>
+                `;
+        } else {
+
+          let membres = yield prepareMembresInitiaux(wotb, dSen, sentries, dicoIdentites, duniterServer);
+
+          const res = yield prepareMembres(req, wotb, duniterServer, membres, idty, dicoIdentites);
+          membres = res.membres;
+          idty = res.idty;
+          const mapPendingCerts = res.mapPendingCerts;
+
+          let lignes = [];
+          for (const membre of membres) {
+            if (req.query.mode == "u2w") {
+              alimenteLignes(wotb, idty, membre, lignes, dicoIdentites, mapPendingCerts);
+            } else {
+              alimenteLignes(wotb, membre, idty, lignes, dicoIdentites, mapPendingCerts);
+            }
+          }
+          searchResult = genereHTMLdeRecherche(lignes, LANG);
+        }
+      }
+
+      // Si le client demande la réponse au format JSON, le faire
+      if (format == 'JSON')
+      {
+	// Send JSON reponse
+	//res.status(200).jsonp( ? )
+      }
+      // Sinon, printer la page html
+      else
+      {
+	// write sentriesHTML
+	let sentriesHTML = sentries
+	    .map((sentry) => `
+		<div class="sentry isSentry"><a href="wotex?lg=${LANG['LG']}&to=${sentry.uid}">${sentry.uid}</a></div>
+	      `)
+	    .join('');
+	
+	res.locals = {
+	  // Les varibles à passer au template
+	  host: req.headers.host.toString(),
+	  searchResult,
+	  sentriesHTML
+	}
+	next()
+      }
+    } catch (e) {
+      // En cas d'exception, afficher le message
+      res.status(500).send('<pre>' + (e.stack || e.message) + '</pre>');
+    }
+
+  });
+
+function traduitCheminEnIdentites(chemins, dicoIdentites) {
+  const cheminsTries = chemins.sort((cheminA, cheminB) => {
+    if (cheminA.length < cheminB.length) {
+      return -1;
+    }
+    if (cheminA.length > cheminB.length) {
+      return 1;
+    }
+    return 0;
+  });
+  if (cheminsTries[0]) {
+    return cheminsTries[0].slice().map((wotb_id) => {
+      return {
+        uid: dicoIdentites[wotb_id].uid,
+        pub: dicoIdentites[wotb_id].pub,
+        wotb_id: wotb_id,
+        statusClass: dicoIdentites[wotb_id].statusClass
+      };
+    });
+  } else {
+    return [];
+  }
+}
+
+function prepareMembresInitiaux(wotb, dSen, sentries, dicoIdentites, duniterServer) {
+  return co(function*() {
+    // Ajout des membres non-sentries
+    const pointsNormaux = wotb.getNonSentries(dSen);
+    const nonSentries = yield pointsNormaux.map((wotb_id) => co(function*() {
+      const identite = (yield duniterServer.dal.idtyDAL.query('SELECT * FROM i_index WHERE wotb_id = ?', [wotb_id]))[0];
+      identite.statusClass = 'isMember';
+      dicoIdentites[identite.wotb_id] = identite;
+      return identite;
+    }));
+    const nonMembres = wotb.getDisabled();
+    const disabled = yield nonMembres.map((wotb_id) => co(function*() {
+      const identite = (yield duniterServer.dal.idtyDAL.query('SELECT * FROM i_index WHERE wotb_id = ?', [wotb_id]))[0];
+      identite.statusClass = 'isNonMember';
+      dicoIdentites[identite.wotb_id] = identite;
+      return identite;
+    }));
+
+    return sentries.concat(nonSentries).concat(disabled);
+  });
+}
+
+function prepareMembres(req, wotb, duniterServer, membres, idty, dicoIdentites) {
+  return co(function*() {
+    const mapPendingCerts = {};
+    const mapPendingIdties = {};
+    const mapSiblings = {};
+    if (req.query.pending) {
+      // Recherche les identités en attente
+      const pendingIdties = yield duniterServer.dal.idtyDAL.sqlListAll();
+      for (const theIdty of pendingIdties) {
+        // Add it to the temp wot
+        theIdty.wotb_id = wotb.addNode();
+        theIdty.statusClass = 'isPending';
+        theIdty.pub = theIdty.pubkey;
+        const siblings = _.where(pendingIdties, { uid: theIdty.uid });
+        if (siblings.length > 1 || mapSiblings[theIdty.uid] !== undefined) {
+          const initialUID = theIdty.uid;
+          mapSiblings[initialUID] = (mapSiblings[initialUID] || 0);
+          theIdty.uid += "[" + mapSiblings[initialUID] + "]";
+          if (theIdty.uid == req.query.to) {
+            idty = theIdty;
+          }
+          mapSiblings[initialUID]++;
+        } else {
+          if (theIdty.uid == req.query.to) {
+            idty = theIdty;
+          }
+        }
+        dicoIdentites[theIdty.wotb_id] = theIdty;
+        mapPendingIdties[theIdty.wotb_id] = theIdty;
+      }
+
+      membres = membres.concat(Object.values(mapPendingIdties));
+
+      // Recherche les certifications en attente
+      const pendingCerts = yield duniterServer.dal.certDAL.sqlListAll();
+      for (const cert of pendingCerts) {
+        const from = _.findWhere(membres, { pub: cert.from });
+        const target = _.findWhere(membres, { hash: cert.target });
+        if (target && from) {
+          wotb.addLink(from.wotb_id, target.wotb_id);
+          mapPendingCerts[[from.wotb_id, target.wotb_id].join('-')] = true;
+        }
+      }
+    }
+    return { idty, membres, mapPendingCerts };
+  });
+}
+
+function alimenteLignes(wotb, source, cible, lignes, dicoIdentites, mapPendingCerts) {
+  const plusCourtsCheminsPossibles = wotb.getPaths(source.wotb_id, cible.wotb_id, MAX_STEP_LOOK);
+  if (plusCourtsCheminsPossibles.length) {
+    const ligne = traduitCheminEnIdentites(plusCourtsCheminsPossibles, dicoIdentites);
+    for (let i = 0; i < ligne.length - 1; i++) {
+      const from_wid = ligne[i].wotb_id;
+      const to_wid = ligne[i + 1].wotb_id;
+      const lien = [from_wid, to_wid].join('-');
+      if (mapPendingCerts[lien]) {
+        ligne[i + 1].pendingCert = true;
+      }
+    }
+    lignes.push(ligne);
+  } else {
+    const identiteObservee = dicoIdentites[source.wotb_id];
+    if (identiteObservee.uid != cible.uid) {
+      lignes.push([identiteObservee,
+        { uid: '?', statusClass: 'isPending', pendingCert: true },
+        { uid: '?', statusClass: 'isPending', pendingCert: true },
+        { uid: '?', statusClass: 'isPending', pendingCert: true },
+        { uid: '?', statusClass: 'isPending', pendingCert: true },
+        { uid: '?', statusClass: 'isPending', pendingCert: true },
+        cible]);
+    }
+  }
+}
+
+function genereHTMLdeRecherche(lignes, LANG) {
+  lignes.sort((ligneA, ligneB) => {
+    if (ligneA.length > ligneB.length) return -1;
+    if (ligneB.length > ligneA.length) return 1;
+    if ((ligneA[1] && ligneA[1] == '?') && (!ligneB[1] || ligneB[1] != '?')) {
+      return 1;
+    }
+    if ((ligneB[1] && ligneB[1] == '?') && (!ligneA[1] || ligneA[1] != '?')) {
+      return -1;
+    }
+    return 0;
+  });
+  lignes.reverse();
+  const chemins = lignes.map((colonnes) => {
+    return `
+    <tr>
+      <td class="${ colonnes[0] && colonnes[0].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[0] && colonnes[0].uid) || ''}">${ (colonnes[0] && colonnes[0].uid) || ''}</td>
+      <td class="${ colonnes[1] && colonnes[1].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[1] && colonnes[1].uid) ? '->' : ''}</td>
+      <td class="${ colonnes[1] && colonnes[1].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[1] && colonnes[1].uid) || ''}">${ (colonnes[1] && colonnes[1].uid) || ''}</td>
+      <td class="${ colonnes[2] && colonnes[2].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[2] && colonnes[2].uid) ? '->' : ''}</td>
+      <td class="${ colonnes[2] && colonnes[2].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[2] && colonnes[2].uid) || ''}">${ (colonnes[2] && colonnes[2].uid) || ''}</td>
+      <td class="${ colonnes[3] && colonnes[3].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[3] && colonnes[3].uid) ? '->' : ''}</td>
+      <td class="${ colonnes[3] && colonnes[3].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[3] && colonnes[3].uid) || ''}">${ (colonnes[3] && colonnes[3].uid) || ''}</td>
+      <td class="${ colonnes[4] && colonnes[4].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[4] && colonnes[4].uid) ? '->' : ''}</td>
+      <td class="${ colonnes[4] && colonnes[4].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[4] && colonnes[4].uid) || ''}">${ (colonnes[4] && colonnes[4].uid) || ''}</td>
+      <td class="${ colonnes[5] && colonnes[5].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[5] && colonnes[5].uid) ? '->' : ''}</td>
+      <td class="isMax ${ colonnes[5] && colonnes[5].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[5] && colonnes[5].uid) || ''}">${ (colonnes[5] && colonnes[5].uid) || ''}</td>
+      <td class="${ colonnes[6] && colonnes[6].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[6] && colonnes[6].uid) ? '->' : ''}</td>
+      <td class="${ colonnes[6] && colonnes[6].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[6] && colonnes[6].uid) || ''}">${ (colonnes[6] && colonnes[6].uid) || ''}</td>
+      <td class="${ colonnes[7] && colonnes[7].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[7] && colonnes[7].uid) ? '->' : ''}</td>
+      <td class="${ colonnes[7] && colonnes[7].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[7] && colonnes[7].uid) || ''}">${ (colonnes[7] && colonnes[7].uid) || ''}</td>
+      <td class="${ colonnes[8] && colonnes[8].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[8] && colonnes[8].uid) ? '->' : ''}</td>
+      <td class="${ colonnes[8] && colonnes[8].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[8] && colonnes[8].uid) || ''}">${ (colonnes[8] && colonnes[8].uid) || ''}</td>
+    </tr>
+  `;
+  }).join('');
+
+  return `
+    <table>
+      <tr>
+        <th>${LANG['STEP']} 0</th>
+        <th class="arrow">-></th>
+        <th>${LANG['STEP']} 1</th>
+        <th class="arrow">-></th>
+        <th>${LANG['STEP']} 2</th>
+        <th class="arrow">-></th>
+        <th>${LANG['STEP']} 3</th>
+        <th class="arrow">-></th>
+        <th>${LANG['STEP']} 4</th>
+        <th class="arrow">-></th>
+        <th class="isMax">${LANG['STEP']} 5 (${LANG['MAX']})</th>
+        <th class="arrow">-></th>
+        <th>${LANG['STEP']} 6</th>
+        <th class="arrow">-></th>
+        <th>${LANG['STEP']} 7</th>
+        <th class="arrow">-></th>
+        <th>${LANG['INFINITY']}</th>
+      </tr>
+      ${chemins}
+    </table>
+  `;
+}
diff --git a/views/Chart.html b/views/Chart.html
index 9f4d58b..3a695de 100755
--- a/views/Chart.html
+++ b/views/Chart.html
@@ -12,7 +12,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
     <td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="wotex?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WOTEX"]}</a></td>
     <td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
@@ -36,4 +36,5 @@ ${(typeof(description) != 'undefined' && help != 'no') ? description:''}<br>
 <script>
   var ctx = document.getElementById("myChart").getContext("2d");
   var myNewChart = new Chart(ctx, ${JSON.stringify(chart)} );
-</script>
\ No newline at end of file
+</script>
+</body></html>
\ No newline at end of file
diff --git a/views/HEAD.html b/views/HEAD.html
index d2dec59..6427bc9 100755
--- a/views/HEAD.html
+++ b/views/HEAD.html
@@ -4,9 +4,9 @@
     <link rel="icon" type="image/png" 
           href="https://librelois.fr/public/duniter.ico" />
     <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
-    <!-- <link href="https://librelois.fr/fonts/ubuntu.css" rel="stylesheet"> -->
+    <!-- <link href="https://librelois.fr/fonts/ubuntu.css" rel="stylesheet"> font-family: 'Ubuntu'; -->
     <style>
       html, body, *, pre {
-        font-family: 'Ubuntu';
+        font-family: "Ubuntu";
       }
     </style>
\ No newline at end of file
diff --git a/views/about.html b/views/about.html
index a3c8482..6b090da 100755
--- a/views/about.html
+++ b/views/about.html
@@ -11,7 +11,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
     <td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="wotex?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WOTEX"]}</a></td>
     <td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
@@ -31,7 +31,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.9">module-0.2.9</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.10">module-0.2.10</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
diff --git a/views/members.html b/views/members.html
index 1b2ea1d..9efcd53 100755
--- a/views/members.html
+++ b/views/members.html
@@ -11,7 +11,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
     <td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="wotex?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WOTEX"]}</a></td>
     <td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
diff --git a/views/willMembers.html b/views/willMembers.html
index 6b65491..0caf8e2 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -11,7 +11,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
     <td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
     <td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
     <td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
-    <!-- <td><a href="pubkeyBalance?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["PUBKEY_BALANCE"]}</a></td> -->
+    <td><a href="wotex?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WOTEX"]}</a></td>
     <td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
     <td>
       <form action="" method="GET">
@@ -60,7 +60,7 @@ ${(help != 'no') ? `
 <!--On parcour toutes les identités-->
 
 <table border="1">
-  <tr><td colspan="${nbMaxCertifs+4}" align='center'>${LANG["TABLE_TITLE1"]} <b>${days}</b> ${LANG["TABLE_TITLE2"]}</td></tr>
+  <tr><td colspan="${nbMaxCertifs+6}" align='center'>${LANG["TABLE_TITLE1"]} <b>${days}</b> ${LANG["TABLE_TITLE2"]}</td></tr>
   <!-- Printer les nom des colonnes-->
   <tr>
     <td align='center'>${LANG['COL_1']}</td><td align='center'>${LANG['COL_2']}</td>
@@ -77,8 +77,7 @@ ${(help != 'no') ? `
       <!--Printer la ligne-->
       <tr>
         <td align="center" style="background:${idty.colorPending=color(idty.expires_on,idtyWindow,250)}">
-        <!--<td align="center" style="background:\${colorPendingIdty}">-->
-          <a href="${wotexURL}?to=${idty['uid']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
+          <a href="wotex?lg=${MENU_LANG['LG']}&to=${idty['uid']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
           ${idty['pubkey'].substring(0, 8)}
           <br>->${idty.pendingCertifications.length}
         </td>
@@ -100,7 +99,7 @@ ${(help != 'no') ? `
           ${ (j<nbMaxCertifs) ? `
             <td align="center" style="background:${(cert.validBlockStamp) ? color(cert.timestampExpire,sigWindow,250) : '#FF8000'}">
             ${j==4?'<b>':''}
-        <a href="${wotexURL}?to=${cert['from']}&pending=on&mode=undefined">${cert['from']}</a>
+        <a href="wotex?lg=${MENU_LANG['LG']}&to=${cert['from']}&pending=on&mode=undefined">${cert['from']}</a>
 	    <br>${timestampToDatetime(cert.timestampExpire)}
 	    <br>#${cert['blockNumber']}
 	    ${ ( !cert.validBlockStamp || cert['timestampWritable'] > currentBlockchainTimestamp ) ? `
@@ -118,7 +117,7 @@ ${(help != 'no') ? `
   `).join('')}
   
   <tr>
-    <td colspan="${4+nbMaxCertifs}" align="center">
+    <td colspan="${nbMaxCertifs+6}" align="center">
       ${LANG['LAST_TR1']} : <b>${idtysListFiltered.length}</b> ${LANG['LAST_TR2']}.
     </td>
   </tr>
diff --git a/views/wotex.html b/views/wotex.html
new file mode 100755
index 0000000..406eaf2
--- /dev/null
+++ b/views/wotex.html
@@ -0,0 +1,173 @@
+<!-- Inclure l'en-tête commun -->
+${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
+  <title>${currencyName}-monit</title>
+		<!-- Style css spécifique de wotex -->
+                <style>
+                .sentry {
+                  float: left;
+                  width: 200px;
+                  height: 21px;
+                  overflow: hidden;
+                }
+                .arrow {
+                  width: 50px;
+                }
+                .isMax {
+                  border-right: 1px dashed gray;
+                }
+                .isSentry, .isSentry a {
+                  text-decoration: none;
+                  color: blue;
+                }
+                .isSentry, .isSentry a:visited {
+                  text-decoration: none;
+                  color: blue;
+                }
+                .isPending, .isPending a {
+                  text-decoration: none;
+                  color: orange !important;
+                  font-weight: bold;
+                }
+                .isMember, .isMember a {
+                  text-decoration: none;
+                  color: black !important;
+                }
+                .isNonMember, .isNonMember a {
+                  text-decoration: none;
+                  color: red !important;
+                }
+                .isPendingCert, .isPendingCert a {
+                  text-decoration: none;
+                  color: orange;
+                  font-weight: bold;
+                }
+                .isPending, .isPending a:visited {
+                  text-decoration: none;
+                  color: orange !important;
+                  font-weight: bold;
+                }
+                .isMember, .isMember a:visited {
+                  text-decoration: none;
+                  color: black !important;
+                }
+                .isNonMember, .isNonMember a:visited {
+                  text-decoration: none;
+                  color: red !important;
+                }
+                .isPendingCert, .isPendingCert a:visited {
+                  text-decoration: none;
+                  color: orange;
+                  font-weight: bold;
+                }
+                td {
+                  text-align: center;
+                }
+              </style>
+              <script type="text/javascript">
+              
+                function onLoadedPage() {
+                  var to = decodeURIComponent(querySt("to") || '');
+                  var pending = querySt("pending") == 'on' ? 'checked' : '';
+                  var mode = querySt("mode");
+                  
+                  document.getElementById('to').value = to || '';
+                  if (window.location.search) {
+                    document.getElementById('pending').checked = pending;
+                  } else {
+                    // Default checked
+                    document.getElementById('pending').checked = 'checked';
+                  }
+                  
+                  if (mode == "u2w") {
+                    document.getElementById('modeu2w').checked = 'checked';
+                  } else {
+                    document.getElementById('modew2u').checked = 'checked';
+                  }
+                  
+                  var params = [
+                    "pending=" + (pending == 'checked' ? 'on' : (!window.location.search ? 'on' : '')),
+                    "mode=" + mode
+                  ];
+                  
+                  var links = document.getElementsByTagName('a');
+                  for (var i = 0; i < links.length; i++) {
+                    links[i].href += '&' + params.join('&');                    
+                  }
+                }
+                
+                function querySt(ji) {
+  
+                    var hu = window.location.search.substring(1);
+                    var gy = hu.split("&");
+                
+                    for (i=0;i<gy.length;i++) {
+                        ft = gy[i].split("=");
+                        if (ft[0] == ji) {
+                            return ft[1];
+                        }
+                    }
+                }
+                
+                function resetAll() {
+                  window.location = '/';
+                  return false;
+                }
+              </script>
+</head>
+  <body onload="onLoadedPage()">
+
+    <!-- Afficher le menu -->
+    <table align="center" width="100%">
+      <tr>
+	<td><a href="willMembers?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WILL_MEMBERS"]}</a></td>
+	<td><a href="members?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS"]}</a></td>
+	<td><a href="membersCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MEMBERS_COUNT"]}</a></td>
+	<td><a href="blockCount?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["BLOCK_COUNT"]}</a></td>
+	<td><a href="monetaryMass?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["MONETARY_MASS"]}</a></td>
+	<td><a href="wotex?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["WOTEX"]}</a></td>
+	<td><a href="about?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}">${MENU_LANG["ABOUT"]}</a></td>
+	<td>
+	  <form action="" method="GET">
+	    <select name="lg" onchange="this.form.submit()">
+	      <option name="lg" value="fr" ${MENU_LANG['LG'] == 'fr' ? 'selected' : ''}>FR
+	      <option name="lg" value="en" ${MENU_LANG['LG'] == 'en' ? 'selected' : ''}>EN
+	    </select>
+	</td>
+    </tr>
+    </table>
+    <hr/>
+
+    <!-- Afficher le titre et le formulaire -->
+    <h1>${LANG['TITLE']}</h1>
+              <form method="GET" action="" onreset="resetAll()">
+                <div>
+                  <label for="to">${LANG['TEST_UID']} :</label>
+                  <input type="text" name="to" id="to">
+                  <br>
+                  <input type="checkbox" name="pending" id="pending" checked="checked">
+                  <label for="pending">${LANG['CHECKBOX_PENDING_DATA']}</label>
+                  <br>
+                  <input type="radio" name="mode" id="modew2u" value="w2u" checked="checked">${LANG['MODE_W2U']}</div>
+                  <input type="radio" name="mode" id="modeu2w" value="u2w">${LANG['MODE_U2W']}</div>
+                  <br>
+                  <input type="submit"/>
+                  <input type="reset" value="Reset"/>
+                </div>
+              </form>
+      <hr/>
+      <!-- Afficher la légende -->
+      <p>${LANG['LEGEND_TITLE']} :</p>
+      <ul>
+	<li><span class="isMember">${LANG['LEGEND_BLACK']}</span></li>
+	<li><span class="isSentry">${LANG['LEGEND_BLUE']}</span></li>
+	<li><span class="isPending">${LANG['LEGEND_ORANGE']}</span></li>
+	<li><span class="isNonMember">${LANG['LEGEND_RED']}</span></li>
+      </ul>
+    <hr/>
+    <!-- Afficher tout les plus courts chemins -->
+    ${searchResult}
+    <!-- Afficher les membres référents -->
+    <h2>${LANG['CURRENT_SENTRIES']} :</h2>
+    ${sentriesHTML}
+  </body>
+</html>
\ No newline at end of file
-- 
GitLab


From ecac93431f922ba0d7c76a65a0b957270224db2d Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Thu, 29 Jun 2017 20:57:11 +0200
Subject: [PATCH 41/48] [mod] willMembers : multi-identities compatibility with
 wotex

---
 routes/willMembers.js  | 18 ++++++++++++++++++
 views/about.html       |  2 +-
 views/willMembers.html |  2 +-
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/routes/willMembers.js b/routes/willMembers.js
index 55ae20a..7861ee8 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -66,6 +66,22 @@ module.exports = (req, res, next) => co(function *() {
 	
 	// récupérer le medianTime du bloc d'émission de l'identité
 	let resultQueryTimeCreateIdty = yield duniterServer.dal.peerDAL.query('SELECT `medianTime` FROM block WHERE `number`=\''+idtyBlockNumber+'\' LIMIT 1');
+	
+	// Récupérer l'identifiant wotex de l'identité (en cas d'identité multiple)
+	let idties = yield duniterServer.dal.idtyDAL.query('' +
+          'SELECT hash, uid, pub, wotb_id FROM i_index WHERE (uid = ? or pub = ?) ' +
+          'UNION ALL ' +
+          'SELECT hash, uid, pubkey as pub, (SELECT NULL) AS wotb_id FROM idty WHERE (uid = ? or pubkey = ?)', [resultQueryIdtys[i].uid, resultQueryIdtys[i].uid, resultQueryIdtys[i].uid, resultQueryIdtys[i].uid]);
+	let wotexId = '';
+	if (idties.length > 1)
+	{
+	  let pos = 0;
+	  for (const idty of idties)
+	  {
+	    if (idty.hash == resultQueryIdtys[i].hash) { wotexId = '['+pos+']'; }
+	    pos++;
+	  }
+	}
 
 	  // Stocker les informations de l'identité
 	  identitiesList.push({
@@ -74,6 +90,7 @@ module.exports = (req, res, next) => co(function *() {
 	      pubkey: resultQueryIdtys[i].pubkey,
 	      uid: resultQueryIdtys[i].uid,
 	      hash: resultQueryIdtys[i].hash,
+	      wotexId: wotexId,
 	      expires_on: resultQueryIdtys[i].expires_on,
 	      nbCert: 0,
 	      nbValidPendingCert: 0,
@@ -277,6 +294,7 @@ module.exports = (req, res, next) => co(function *() {
 	    
 	    idtysListOrdered.push({
 	    uid: identitiesList[idMax].uid,
+	    wotexId: identitiesList[idMax].wotexId,
 	    creationTimestamp: identitiesList[idMax].creationTimestamp,
 	    pubkey: identitiesList[idMax].pubkey,
 	    BlockNumber: identitiesList[idMax].BlockNumber,
diff --git a/views/about.html b/views/about.html
index 6b090da..c237dc3 100755
--- a/views/about.html
+++ b/views/about.html
@@ -33,6 +33,6 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 </div><br>
 <div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.10">module-0.2.10</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
-<div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
+<div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/c-geek">cgeek</a> (willMembers and wotex),<a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
 <div align="left">If you want you can <a href="?lg=${MENU_LANG['LG']}&help=no">disable help</a>.</div><br>
\ No newline at end of file
diff --git a/views/willMembers.html b/views/willMembers.html
index 0caf8e2..0a0c5ed 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -77,7 +77,7 @@ ${(help != 'no') ? `
       <!--Printer la ligne-->
       <tr>
         <td align="center" style="background:${idty.colorPending=color(idty.expires_on,idtyWindow,250)}">
-          <a href="wotex?lg=${MENU_LANG['LG']}&to=${idty['uid']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
+          <a href="wotex?lg=${MENU_LANG['LG']}&to=${idty['uid']}${idty['wotexId']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
           ${idty['pubkey'].substring(0, 8)}
           <br>->${idty.pendingCertifications.length}
         </td>
-- 
GitLab


From 622f3e61991f019bf483634bc38588dcf28d1faa Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Thu, 29 Jun 2017 20:58:27 +0200
Subject: [PATCH 42/48] upgrade to version module-0.2.11

---
 views/about.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/views/about.html b/views/about.html
index c237dc3..6e98480 100755
--- a/views/about.html
+++ b/views/about.html
@@ -31,7 +31,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.10">module-0.2.10</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.11">module-0.2.11</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/c-geek">cgeek</a> (willMembers and wotex),<a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab


From 771f961df8ffe0809fe9ceb067786ae3ab77eb9c Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Thu, 29 Jun 2017 22:07:16 +0200
Subject: [PATCH 43/48] [enh] fix #45

---
 routes/index.js        | 11 -----------
 routes/willMembers.js  | 35 +++++++++++++++++++++--------------
 routes/wotex.js        | 23 ++++++++++++-----------
 views/willMembers.html |  9 ++++++---
 views/wotex.html       |  4 +++-
 5 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/routes/index.js b/routes/index.js
index 41be68a..921e1dd 100755
--- a/routes/index.js
+++ b/routes/index.js
@@ -117,15 +117,4 @@ app.get('/wotex', require(__dirname + '/wotex.js'), (req, res)=> res.render('wot
          })
  )
 
-
-/***************************************
-* Solde d'une clé
-***************************************/
-/*app.get('/pubkeyBalance', require('${__dirname}/../lib/updateCache.js'), require(__dirname + '/pubkeyBalance.js'), (req, res)=> res.render('Chart.html', {
-	    help: req.query.help,
-            MENU_LANG: getLang(`${__dirname}/../lg/menu_${req.query.lg||'fr'}.txt`),
-            LANG: getLang(`${__dirname}/../lg/pubkeyBalance_${req.query.lg||'fr'}.txt`)
-         })
- )*/
-
 module.exports = app
\ No newline at end of file
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 7861ee8..52c71a4 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -64,8 +64,8 @@ module.exports = (req, res, next) => co(function *() {
 	let idtyBlockStamp = resultQueryIdtys[i].buid.split("-");
 	let idtyBlockNumber = idtyBlockStamp[0];
 	
-	// récupérer le medianTime du bloc d'émission de l'identité
-	let resultQueryTimeCreateIdty = yield duniterServer.dal.peerDAL.query('SELECT `medianTime` FROM block WHERE `number`=\''+idtyBlockNumber+'\' LIMIT 1');
+	// récupérer le medianTime et le hash du bloc d'émission de l'identité
+	let idtyEmittedBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime`,`hash` FROM block WHERE `number`=\''+idtyBlockNumber+'\' LIMIT 1');
 	
 	// Récupérer l'identifiant wotex de l'identité (en cas d'identité multiple)
 	let idties = yield duniterServer.dal.idtyDAL.query('' +
@@ -82,11 +82,16 @@ module.exports = (req, res, next) => co(function *() {
 	    pos++;
 	  }
 	}
+	
+	// vérifier la validité du blockstamp de l'identité
+	let validIdtyBlockStamp = false;
+	if (idtyEmittedBlock[0].hash == idtyBlockStamp[1])
+	{ validIdtyBlockStamp = true; }
 
 	  // Stocker les informations de l'identité
 	  identitiesList.push({
 	      BlockNumber: idtyBlockNumber,
-	      creationTimestamp: resultQueryTimeCreateIdty[0].medianTime,
+	      creationTimestamp: idtyEmittedBlock[0].medianTime,
 	      pubkey: resultQueryIdtys[i].pubkey,
 	      uid: resultQueryIdtys[i].uid,
 	      hash: resultQueryIdtys[i].hash,
@@ -94,7 +99,8 @@ module.exports = (req, res, next) => co(function *() {
 	      expires_on: resultQueryIdtys[i].expires_on,
 	      nbCert: 0,
 	      nbValidPendingCert: 0,
-	      registrationAvailability: 0
+	      registrationAvailability: 0,
+	      validBlockStamp: validIdtyBlockStamp
 	  });
 	  idtysPendingCertifsList.push(new Array());
 	
@@ -293,16 +299,17 @@ module.exports = (req, res, next) => co(function *() {
 	    wotb.clear();
 	    
 	    idtysListOrdered.push({
-	    uid: identitiesList[idMax].uid,
-	    wotexId: identitiesList[idMax].wotexId,
-	    creationTimestamp: identitiesList[idMax].creationTimestamp,
-	    pubkey: identitiesList[idMax].pubkey,
-	    BlockNumber: identitiesList[idMax].BlockNumber,
-	    expires_on: identitiesList[idMax].expires_on,
-	    nbValidPendingCert: identitiesList[idMax].nbValidPendingCert,
-	    isOutdistanced,
-	    membership: membership,
-	    pendingCertifications: idtysPendingCertifsList[idMax]
+	      uid: identitiesList[idMax].uid,
+	      wotexId: identitiesList[idMax].wotexId,
+	      creationTimestamp: identitiesList[idMax].creationTimestamp,
+	      pubkey: identitiesList[idMax].pubkey,
+	      BlockNumber: identitiesList[idMax].BlockNumber,
+	      expires_on: identitiesList[idMax].expires_on,
+	      nbValidPendingCert: identitiesList[idMax].nbValidPendingCert,
+	      isOutdistanced,
+	      membership: membership,
+	      pendingCertifications: idtysPendingCertifsList[idMax],
+	      validBlockStamp: identitiesList[idMax].validBlockStamp
 	    });
 	  }
 	}
diff --git a/routes/wotex.js b/routes/wotex.js
index 5d76847..13bee4f 100755
--- a/routes/wotex.js
+++ b/routes/wotex.js
@@ -13,6 +13,7 @@ module.exports = (req, res, next) => co(function *() {
     try {
       // get GET parameters
       var format = req.query.format || 'HTML';
+      var help = req.query.help || 'yes';
       
       // get lg file
       const LANG = getLang(`${__dirname}/../lg/wotex_${req.query.lg||'fr'}.txt`);
@@ -71,7 +72,7 @@ module.exports = (req, res, next) => co(function *() {
               alimenteLignes(wotb, membre, idty, lignes, dicoIdentites, mapPendingCerts);
             }
           }
-          searchResult = genereHTMLdeRecherche(lignes, LANG);
+          searchResult = genereHTMLdeRecherche(lignes, LANG, help);
         }
       }
 
@@ -227,7 +228,7 @@ function alimenteLignes(wotb, source, cible, lignes, dicoIdentites, mapPendingCe
   }
 }
 
-function genereHTMLdeRecherche(lignes, LANG) {
+function genereHTMLdeRecherche(lignes, LANG, help) {
   lignes.sort((ligneA, ligneB) => {
     if (ligneA.length > ligneB.length) return -1;
     if (ligneB.length > ligneA.length) return 1;
@@ -243,23 +244,23 @@ function genereHTMLdeRecherche(lignes, LANG) {
   const chemins = lignes.map((colonnes) => {
     return `
     <tr>
-      <td class="${ colonnes[0] && colonnes[0].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[0] && colonnes[0].uid) || ''}">${ (colonnes[0] && colonnes[0].uid) || ''}</td>
+      <td class="${ colonnes[0] && colonnes[0].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[0] && colonnes[0].uid) || ''}">${ (colonnes[0] && colonnes[0].uid) || ''}</td>
       <td class="${ colonnes[1] && colonnes[1].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[1] && colonnes[1].uid) ? '->' : ''}</td>
-      <td class="${ colonnes[1] && colonnes[1].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[1] && colonnes[1].uid) || ''}">${ (colonnes[1] && colonnes[1].uid) || ''}</td>
+      <td class="${ colonnes[1] && colonnes[1].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[1] && colonnes[1].uid) || ''}">${ (colonnes[1] && colonnes[1].uid) || ''}</td>
       <td class="${ colonnes[2] && colonnes[2].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[2] && colonnes[2].uid) ? '->' : ''}</td>
-      <td class="${ colonnes[2] && colonnes[2].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[2] && colonnes[2].uid) || ''}">${ (colonnes[2] && colonnes[2].uid) || ''}</td>
+      <td class="${ colonnes[2] && colonnes[2].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[2] && colonnes[2].uid) || ''}">${ (colonnes[2] && colonnes[2].uid) || ''}</td>
       <td class="${ colonnes[3] && colonnes[3].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[3] && colonnes[3].uid) ? '->' : ''}</td>
-      <td class="${ colonnes[3] && colonnes[3].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[3] && colonnes[3].uid) || ''}">${ (colonnes[3] && colonnes[3].uid) || ''}</td>
+      <td class="${ colonnes[3] && colonnes[3].statusClass }"><a href="wotex?lg=$&help=${help}&to=${ (colonnes[3] && colonnes[3].uid) || ''}">${ (colonnes[3] && colonnes[3].uid) || ''}</td>
       <td class="${ colonnes[4] && colonnes[4].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[4] && colonnes[4].uid) ? '->' : ''}</td>
-      <td class="${ colonnes[4] && colonnes[4].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[4] && colonnes[4].uid) || ''}">${ (colonnes[4] && colonnes[4].uid) || ''}</td>
+      <td class="${ colonnes[4] && colonnes[4].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[4] && colonnes[4].uid) || ''}">${ (colonnes[4] && colonnes[4].uid) || ''}</td>
       <td class="${ colonnes[5] && colonnes[5].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[5] && colonnes[5].uid) ? '->' : ''}</td>
-      <td class="isMax ${ colonnes[5] && colonnes[5].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[5] && colonnes[5].uid) || ''}">${ (colonnes[5] && colonnes[5].uid) || ''}</td>
+      <td class="isMax ${ colonnes[5] && colonnes[5].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[5] && colonnes[5].uid) || ''}">${ (colonnes[5] && colonnes[5].uid) || ''}</td>
       <td class="${ colonnes[6] && colonnes[6].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[6] && colonnes[6].uid) ? '->' : ''}</td>
-      <td class="${ colonnes[6] && colonnes[6].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[6] && colonnes[6].uid) || ''}">${ (colonnes[6] && colonnes[6].uid) || ''}</td>
+      <td class="${ colonnes[6] && colonnes[6].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[6] && colonnes[6].uid) || ''}">${ (colonnes[6] && colonnes[6].uid) || ''}</td>
       <td class="${ colonnes[7] && colonnes[7].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[7] && colonnes[7].uid) ? '->' : ''}</td>
-      <td class="${ colonnes[7] && colonnes[7].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[7] && colonnes[7].uid) || ''}">${ (colonnes[7] && colonnes[7].uid) || ''}</td>
+      <td class="${ colonnes[7] && colonnes[7].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[7] && colonnes[7].uid) || ''}">${ (colonnes[7] && colonnes[7].uid) || ''}</td>
       <td class="${ colonnes[8] && colonnes[8].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[8] && colonnes[8].uid) ? '->' : ''}</td>
-      <td class="${ colonnes[8] && colonnes[8].statusClass }"><a href="wotex?lg=${LANG['LG']}&to=${ (colonnes[8] && colonnes[8].uid) || ''}">${ (colonnes[8] && colonnes[8].uid) || ''}</td>
+      <td class="${ colonnes[8] && colonnes[8].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[8] && colonnes[8].uid) || ''}">${ (colonnes[8] && colonnes[8].uid) || ''}</td>
     </tr>
   `;
   }).join('');
diff --git a/views/willMembers.html b/views/willMembers.html
index 0a0c5ed..e0d14cd 100755
--- a/views/willMembers.html
+++ b/views/willMembers.html
@@ -76,13 +76,16 @@ ${(help != 'no') ? `
       
       <!--Printer la ligne-->
       <tr>
-        <td align="center" style="background:${idty.colorPending=color(idty.expires_on,idtyWindow,250)}">
-          <a href="wotex?lg=${MENU_LANG['LG']}&to=${idty['uid']}${idty['wotexId']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
+        <td align="center" style="background:${(idty.validBlockStamp) ? idty.colorPending=color(idty.expires_on,idtyWindow,250) : idty.colorPending='#FF8000'}">
+          <a href="wotex?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}&to=${idty['uid']}${idty['wotexId']}&pending=on&mode=undefined">${idty['uid'].substring(0, 20)}</a><br>
           ${idty['pubkey'].substring(0, 8)}
           <br>->${idty.pendingCertifications.length}
         </td>
         <td align='center' style="background:${idty.colorPending}">${timestampToDatetime(idty['creationTimestamp'])}<br>
         #${idty['BlockNumber']}
+        ${(!idty.validBlockStamp) ? `
+          <br><font color="DarkRed">[${LANG['INVALID_BLOCKSTAMP']}]</font>
+        `:``}
         </td>
         <td align='center' style="background:${idty.colorPending}">
         ${timestampToDatetime(idty.expires_on)}</td>
@@ -99,7 +102,7 @@ ${(help != 'no') ? `
           ${ (j<nbMaxCertifs) ? `
             <td align="center" style="background:${(cert.validBlockStamp) ? color(cert.timestampExpire,sigWindow,250) : '#FF8000'}">
             ${j==4?'<b>':''}
-        <a href="wotex?lg=${MENU_LANG['LG']}&to=${cert['from']}&pending=on&mode=undefined">${cert['from']}</a>
+        <a href="wotex?lg=${MENU_LANG['LG']}${(typeof(help) != 'undefined' && help == 'no') ? '&help=no':''}&to=${cert['from']}&pending=on&mode=undefined">${cert['from']}</a>
 	    <br>${timestampToDatetime(cert.timestampExpire)}
 	    <br>#${cert['blockNumber']}
 	    ${ ( !cert.validBlockStamp || cert['timestampWritable'] > currentBlockchainTimestamp ) ? `
diff --git a/views/wotex.html b/views/wotex.html
index 406eaf2..86d8dfc 100755
--- a/views/wotex.html
+++ b/views/wotex.html
@@ -156,6 +156,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
               </form>
       <hr/>
       <!-- Afficher la légende -->
+      ${(typeof(help) == 'undefined' || help != 'no') ? `
       <p>${LANG['LEGEND_TITLE']} :</p>
       <ul>
 	<li><span class="isMember">${LANG['LEGEND_BLACK']}</span></li>
@@ -163,7 +164,8 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 	<li><span class="isPending">${LANG['LEGEND_ORANGE']}</span></li>
 	<li><span class="isNonMember">${LANG['LEGEND_RED']}</span></li>
       </ul>
-    <hr/>
+      <hr/>
+      `:``}
     <!-- Afficher tout les plus courts chemins -->
     ${searchResult}
     <!-- Afficher les membres référents -->
-- 
GitLab


From 66e87ed1abe6074bf49419b2e9a0da5df290181b Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Thu, 29 Jun 2017 22:13:21 +0200
Subject: [PATCH 44/48] [fix] fix #43

---
 views/HEAD.html | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/views/HEAD.html b/views/HEAD.html
index 6427bc9..6e69fe4 100755
--- a/views/HEAD.html
+++ b/views/HEAD.html
@@ -6,6 +6,9 @@
     <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
     <!-- <link href="https://librelois.fr/fonts/ubuntu.css" rel="stylesheet"> font-family: 'Ubuntu'; -->
     <style>
+      html {
+	overflow-y: scroll;
+      }
       html, body, *, pre {
         font-family: "Ubuntu";
       }
-- 
GitLab


From 4ac3d030abf555c437c6806ca07cf873e85f3692 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Thu, 29 Jun 2017 22:31:33 +0200
Subject: [PATCH 45/48] [fix] fix #44

---
 lg/membersCount_en.txt |  1 +
 lg/membersCount_fr.txt |  1 +
 lib/updateCache.js     |  4 ++--
 routes/membersCount.js | 12 ++++++------
 4 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/lg/membersCount_en.txt b/lg/membersCount_en.txt
index 6a5ecce..a9e753c 100755
--- a/lg/membersCount_en.txt
+++ b/lg/membersCount_en.txt
@@ -1,3 +1,4 @@
+LAST_BLOCK last block
 BEGIN Begin
 END End
 STEP step
diff --git a/lg/membersCount_fr.txt b/lg/membersCount_fr.txt
index b890406..997555b 100755
--- a/lg/membersCount_fr.txt
+++ b/lg/membersCount_fr.txt
@@ -1,3 +1,4 @@
+LAST_BLOCK dernier bloc
 BEGIN Début
 END Fin
 STEP précision
diff --git a/lib/updateCache.js b/lib/updateCache.js
index 25cdf90..f053501 100755
--- a/lib/updateCache.js
+++ b/lib/updateCache.js
@@ -108,7 +108,7 @@ module.exports = (req, res, next) => co(function *() {
       {
 	  case "blocks": unitTime = 3600; cache.onlyDate = false; cache.stepUnit = "blocks"; break;
 	  case "hours": unitTime = 3600; cache.onlyDate = false; cache.stepUnit = "hours"; break;
-	  case "days": unitTime = 86400; cache.onlyDate = false; cache.stepUnit = "days"; break;
+	  case "days": unitTime = 86400; cache.onlyDate = true; cache.stepUnit = "days"; break;
 	  case "weeks": unitTime = 604800; cache.onlyDate = true; cache.stepUnit = "weeks"; break;
 	  case "months": unitTime = 18144000; cache.onlyDate = true; cache.stepUnit = "months"; break;
 	  case "years": unitTime = 31557600; cache.onlyDate = true; cache.stepUnit = "years"; break;
@@ -117,7 +117,7 @@ module.exports = (req, res, next) => co(function *() {
     // Default values
     else
     {
-      unitTime = 86400; cache.onlyDate = false; cache.stepUnit = "days";
+      unitTime = 86400; cache.onlyDate = true; cache.stepUnit = "days";
     }
     
     // get endBlock
diff --git a/routes/membersCount.js b/routes/membersCount.js
index cfacf97..0bafbcf 100755
--- a/routes/membersCount.js
+++ b/routes/membersCount.js
@@ -14,6 +14,9 @@ module.exports = (req, res, next) => co(function *() {
     // get GET parameters
     var format = req.query.format || 'HTML';
     
+    // get lg file
+    const LANG = getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`);
+    
     // get medianTime of beginBlock
     var beginBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime`,`hash` FROM block WHERE `fork`=0 AND `number` = '+cache.beginBlock[0].number+' LIMIT 1');
     
@@ -32,7 +35,7 @@ module.exports = (req, res, next) => co(function *() {
     }
     
     // Initialize nextStepTime, stepIssuerCount and bStep
-    var nextStepTime = blockchain[0].medianTime;
+    var nextStepTime = blockchain[0].medianTime - (blockchain[0].medianTime % 86400);
     let stepIssuerCount = 0;
     let bStep = 0;
 
@@ -53,7 +56,7 @@ module.exports = (req, res, next) => co(function *() {
 	tabMembersCount.push({
 	    blockNumber: blockchain[b].number,
 	    timestamp: blockchain[b].medianTime,
-	    dateTime: timestampToDatetime(blockchain[b].medianTime),
+	    dateTime: timestampToDatetime(blockchain[b].medianTime, cache.onlyDate),
 	    membersCount: blockchain[b].membersCount,
 	    sentriesCount: cache.blockchain[cacheIndex].sentries,
 	    issuersCount: parseInt(stepIssuerCount/bStep)
@@ -69,7 +72,7 @@ module.exports = (req, res, next) => co(function *() {
     tabMembersCount.push({
 	    blockNumber: blockchain[blockchain.length-1].number,
 	    timestamp: blockchain[blockchain.length-1].medianTime,
-	    dateTime: timestampToDatetime(blockchain[blockchain.length-1].medianTime),
+	    dateTime: LANG['LAST_BLOCK'],
 	    membersCount: blockchain[blockchain.length-1].membersCount,
 	    sentriesCount: cache.blockchain[cache.blockchain.length-1].sentries,
 	    issuersCount: blockchain[blockchain.length-1].issuersCount
@@ -79,9 +82,6 @@ module.exports = (req, res, next) => co(function *() {
       res.status(200).jsonp( tabMembersCount )
     else
     {
-      // get lg file
-      const LANG = getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`);
-      
       // GET parameters
       var unit = req.query.unit == 'relative' ? 'relative' : 'quantitative';
       var massByMembers = req.query.massByMembers == 'no' ? 'no' : 'yes';
-- 
GitLab


From 9b4a2bc583c97bdc2c45cacc090306af4bcfc615 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Fri, 30 Jun 2017 14:33:42 +0200
Subject: [PATCH 46/48] [mod] members : add traduction en

---
 lg/members_en.txt      | 29 +++++++++++++++++++++++++++-
 lg/members_fr.txt      | 29 +++++++++++++++++++++++++++-
 package.json           |  1 -
 routes/membersCount.js | 10 +++++++++-
 routes/willMembers.js  | 11 +++++++++--
 views/members.html     | 44 +++++++++++++++++++++---------------------
 6 files changed, 96 insertions(+), 28 deletions(-)

diff --git a/lg/members_en.txt b/lg/members_en.txt
index fef7489..e6f6308 100755
--- a/lg/members_en.txt
+++ b/lg/members_en.txt
@@ -1 +1,28 @@
-SUBMIT_BUTTON submit
\ No newline at end of file
+FORM1 days - sort by
+SORT_BY_IDTY_WRITTEN identity written time
+SORT_BY_EXPIRE_MEMBERSHIP expire membership time
+SORT_LAST_RENEWAL last renewal time
+SORT_BY_OLDEST_SIG oldest sig time
+SORT_BY_LAST_SIG last sig time
+SORT_BY_SIG_COUNT certifications count
+ORDER_BY in the following order
+ASC ascending
+DESC descending
+SUBMIT_BUTTON submit
+CHECKBOX_PENDING_SIGS Include pending certifications.
+LEGEND_AVAILABILITY [availability : means this certification may already be written in the next block.]
+CURRENT_BLOCKCHAIN_TIME Current blockchain time
+TABLE_TITLE Members that will expire in less than
+DAYS days
+COL_UID uid
+COL_IDTY_WRITTEN_TIME identity written time
+COL_LAST_RENEWAL last renewal
+COL_EXPIRE_MEMBERSHIP expire membership
+COL_LIST_RECEIVED_CERT list received certifications
+COL_LIST_EMITTED_CERT list emitted certifications
+LAST2OLDEST récentes -> anciennes
+OLDEST2LAST anciennes -> récentes
+EMITTED emitted
+WRITTEN written
+OVERALL Overall
+MEMBERS members
\ No newline at end of file
diff --git a/lg/members_fr.txt b/lg/members_fr.txt
index 5ed9c42..83798b7 100755
--- a/lg/members_fr.txt
+++ b/lg/members_fr.txt
@@ -1 +1,28 @@
-SUBMIT_BUTTON recharger
\ No newline at end of file
+FORM1 jours - tri par
+SORT_BY_IDTY_WRITTEN date d'obtention du statut de membre
+SORT_BY_EXPIRE_MEMBERSHIP date d\'expiration du membership
+SORT_LAST_RENEWAL date de dernier renouvellement
+SORT_BY_OLDEST_SIG date de plus vielle certification
+SORT_BY_LAST_SIG date de plus récente certification
+SORT_BY_SIG_COUNT nombre de certifications reçues
+ORDER_BY dans l'ordre
+ASC croissant
+DESC décroissant
+SUBMIT_BUTTON recharger
+CHECKBOX_PENDING_SIGS Inclure les certifications en piscine.
+LEGEND_AVAILABILITY [disponibilité : date à partir de laquelle cette certification pourra être écrite compte tenu de sigPeriod]
+CURRENT_BLOCKCHAIN_TIME Temps Blockchain actuel
+TABLE_TITLE Membres dont le statut de membre va expirer dans moins de
+DAYS jours
+COL_UID uid
+COL_IDTY_WRITTEN_TIME obtention statut membre
+COL_LAST_RENEWAL dernier renouvellement
+COL_EXPIRE_MEMBERSHIP date d'expiration du membre
+COL_LIST_RECEIVED_CERT liste des certifications reçues
+COL_LIST_EMMITED_CERT liste des certifications émises
+LAST2OLDEST récentes -> anciennes
+OLDEST2LAST anciennes -> récentes
+EMITTED émise
+WRITTEN écrite
+OVERALL Total
+MEMBERS membres
\ No newline at end of file
diff --git a/package.json b/package.json
index 392336c..5eb67f1 100755
--- a/package.json
+++ b/package.json
@@ -18,7 +18,6 @@
     "request": "^2.81.0",
     "request-promise": "4.2.0",
     "rimraf": "^2.6.1",
-    "sqlite3": "3.1.x",
     "tmp": "^0.0.31",
     "underscore": "1.8.3",
     "ws": "1.1.1"
diff --git a/routes/membersCount.js b/routes/membersCount.js
index 0bafbcf..1a01b70 100755
--- a/routes/membersCount.js
+++ b/routes/membersCount.js
@@ -35,9 +35,17 @@ module.exports = (req, res, next) => co(function *() {
     }
     
     // Initialize nextStepTime, stepIssuerCount and bStep
-    var nextStepTime = blockchain[0].medianTime - (blockchain[0].medianTime % 86400);
+    var nextStepTime = blockchain[0].medianTime;
     let stepIssuerCount = 0;
     let bStep = 0;
+    
+    // Adapt nextStepTime initial value
+    switch (cache.stepUnit)
+    {
+	  case "hours": nextStepTime -= (blockchain[0].medianTime % 3600); break;
+	  case "days":case "weeks":case "months":case "years": nextStepTime -= (blockchain[0].medianTime % 86400); break;
+	  default: break;
+    }
 
     // fill tabMembersCount
     var tabMembersCount = [];
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 52c71a4..6cc14b8 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -1,7 +1,9 @@
 "use strict";
 
 const co = require('co')
-const crypto = require('crypto');
+const crypto = require('crypto')
+//const wotb = require('wotb')
+
 const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
 const MIN_WILLMEMBERS_UPDATE_FREQ = 150;
@@ -54,6 +56,9 @@ module.exports = (req, res, next) => co(function *() {
       countMembersWithSigQtyValidCert = 0;
       lastUpgradeTime = Math.floor(Date.now() / 1000);
       
+      // Alimenter wotb avec la toile Ğ1
+      //const wotbInstance = wotb.newFileInstance(duniterServer.home + '/wotb.bin');
+      
       // Récupérer la liste des identités en piscine
       const resultQueryIdtys = yield duniterServer.dal.peerDAL.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on` FROM identities_pending WHERE `member`=0');
 	
@@ -277,6 +282,7 @@ module.exports = (req, res, next) => co(function *() {
 	  if (!doubloon)
 	  {
 	    // Tester la distance à l'aide des certifications disponibles
+	    //let wotb = wotbInstance.memCopy();
 	    let wotb = duniterServer.dal.wotb.memCopy();
 
 	    let pendingIdtyWID = wotb.addNode()
@@ -284,7 +290,8 @@ module.exports = (req, res, next) => co(function *() {
 	    {
 	      wotb.addLink(cert.wid, pendingIdtyWID)
 	    }
-	    let isOutdistanced = wotb.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
+	    let detailedDistance = wotb.detailedDistance(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
+	    let isOutdistanced = detailedDistance.isOutdistanced;
 
 	    // Tester la présence de l'adhésion
 	    let membership = null
diff --git a/views/members.html b/views/members.html
index 9efcd53..b9472b5 100755
--- a/views/members.html
+++ b/views/members.html
@@ -25,38 +25,38 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <hr>
 
 <!-- Afficher le formulaire -->
-<input type="number" name="d" value="${days}"/>jours - tri par <select name="sort_by">
-<option name="sort_by" value ="idtyWritten">date d\'obtention du statut de membre
-<option name="sort_by" value ="expireMembership" ${sort_by == 'expireMembership' ? 'selected' : ''}>date d\'expiration du membership
-<option name="sort_by" value ="lastRenewal" ${sort_by == 'lastRenewal' ? 'selected' : ''}>date de dernier renouvellement
-<option name="sort_by" value ="oldestSig" ${sort_by == 'oldestSig' ? 'selected' : ''}>date de plus vielle certification
-<option name="sort_by" value ="lastSig" ${sort_by == 'lastSig' ? 'selected' : ''}>date de plus récente certification
-<option name="sort_by" value ="sigCount" ${sort_by == 'sigCount' ? 'selected' : ''}>nombre de certifications reçues
-</select> dans l\'ordre <select name="order">
-<option name="order" value ="asc">croissant
-<option name="order" value ="desc" ${order == 'desc' ? 'selected' : ''}>décroissant</select>
+<input type="number" name="d" value="${days}"/>${LANG["FORM1"]} <select name="sort_by">
+<option name="sort_by" value ="idtyWritten">${LANG["SORT_BY_IDTY_WRITTEN"]}
+<option name="sort_by" value ="expireMembership" ${sort_by == 'expireMembership' ? 'selected' : ''}>${LANG["SORT_BY_EXPIRE_MEMBERSHIP"]} date d\'expiration du membership
+<option name="sort_by" value ="lastRenewal" ${sort_by == 'lastRenewal' ? 'selected' : ''}>${LANG["SORT_LAST_RENEWAL"]} date de dernier renouvellement
+<option name="sort_by" value ="oldestSig" ${sort_by == 'oldestSig' ? 'selected' : ''}>${LANG["SORT_BY_OLDEST_SIG"]} date de plus vielle certification
+<option name="sort_by" value ="lastSig" ${sort_by == 'lastSig' ? 'selected' : ''}>${LANG["SORT_BY_LAST_SIG"]} date de plus récente certification
+<option name="sort_by" value ="sigCount" ${sort_by == 'sigCount' ? 'selected' : ''}>${LANG["SORT_BY_SIG_COUNT"]} nombre de certifications reçues
+</select> ${LANG["ORDER_BY"]} <select name="order">
+<option name="order" value ="asc"> ${LANG["ASC"]}
+<option name="order" value ="desc" ${order == 'desc' ? 'selected' : ''}> ${LANG["DESC"]}</select>
 <input type="submit" value="envoyer"><br>
-<input type="checkbox" name="pendingSigs" value="yes" ${pendingSigs == 'yes' ? 'checked' : ''}>Inclure les certifications en piscine.</form><br>
+<input type="checkbox" name="pendingSigs" value="yes" ${pendingSigs == 'yes' ? 'checked' : ''}>${LANG["CHECKBOX_PENDING_SIGS"]}</form><br>
 
 <!-- Afficher la légende -->
 <br>
-${(pendingSigs == 'yes' && help != 'no') ? ` [inscriptible : date à partir de laquelle cette certification pourra être écrite compte tenu de sigPeriod]<br>` : ''}
+${(pendingSigs == 'yes' && help != 'no') ? ` ${LANG["LEGEND_AVAILABILITY"]}<br>` : ''}
 
 <!-- Afficher le currentBlockchainTimestamp -->
-<i>Temps Blockchain actuel : ${timestampToDatetime(currentBlockchainTimestamp)}.</i><br>
+<i>${LANG["CURRENT_BLOCKCHAIN_TIME"]} : ${timestampToDatetime(currentBlockchainTimestamp)}.</i><br>
 <br>
 
 <!-- On parcour tout les membres pour afficher ceux dont la date d'expiration est dans moins de 'd' jours -->
-<b>Membres dont le statut de membre va expirer dans moins de ${days} jours :</b>
+<b>${LANG["TABLE_TITLE"]} ${days} ${LANG["DAYS"]} :</b>
 <table border="1">
   <!-- Printer les nom des colonnes -->
   <tr>
-    <td align="center">uid</td>
-    <td align="center">obtention statut membre</td>
-    <td align="center">dernier renouvellement</td>
-    <td align="center">date d'expiration du membre</td>
+    <td align="center">${LANG["COL_UID"]}</td>
+    <td align="center">${LANG["COL_IDTY_WRITTEN_TIME"]}</td>
+    <td align="center">${LANG["COL_LAST_RENEWAL"]}</td>
+    <td align="center">${LANG["COL_EXPIRE_MEMBERSHIP"]}</td>
     <td style="background:#000000">-</td>
-    <td align="left" colspan="${nbMaxCertifs}">liste des certifications reçues (${sort_by == 'lastSig' ? 'récentes -> anciennes' : 'anciennes -> récentes'})</td>
+    <td align="left" colspan="${nbMaxCertifs}">liste des certifications reçues (${sort_by == 'lastSig' ? LANG["LAST2OLDEST"] : LANG["OLDEST2LAST"]})</td>
   </tr>
   
   ${membersListFiltered
@@ -95,7 +95,7 @@ ${(pendingSigs == 'yes' && help != 'no') ? ` [inscriptible : date à partir de l
               <td align="center" style="background:${color(certification.timestampExpire,sigWindow,200)})">
                 ${certification.from}<br>
                 ${timestampToDatetime(certification.timestampExpire)}<br>
-                émise #${certification.blockNumber}<br>
+                ${LANG["EMITTED"]} #${certification.blockNumber}<br>
                 [inscriptible ${timestampToDatetime(certification.timestampWritable)}]
               </td>
             `).join('') 
@@ -107,14 +107,14 @@ ${(pendingSigs == 'yes' && help != 'no') ? ` [inscriptible : date à partir de l
           <td align="center" style="background:hsla(${proportion(certification.timestampExpire,sigValidity,0,120)}, 100%, 50%, 1 )">
             ${certification.issuer}<br>
             ${timestampToDatetime(certification.timestampExpire)}<br>
-            écrite #${certification.writtenBloc}
+            ${LANG["WRITTEN"]} #${certification.writtenBloc}
           </td>
         `).join('')}
       </tr>
     `).join('')
   }
   <tr>
-    <td colspan="${4+nbMaxCertifs}" align="center"> total : <b>${membersListFiltered.length}</b> membres.</td>
+    <td colspan="${4+nbMaxCertifs}" align="center"> ${LANG["OVERALL"]} : <b>${membersListFiltered.length}</b> ${LANG["MEMBERS"]}.</td>
   </tr>
 </table><br>
 
-- 
GitLab


From b0d7e85ddac7a090d1b48ce62ffc7f6c8c9df552 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Fri, 30 Jun 2017 18:59:43 +0200
Subject: [PATCH 47/48] [enh] fix #4

---
 lg/members_en.txt     |   7 ++-
 lg/members_fr.txt     |  11 ++--
 package.json          |   3 +-
 routes/members.js     | 116 ++++++++++++++++++++++++++----------------
 routes/willMembers.js |  23 +++++----
 views/about.html      |   2 +-
 views/members.html    |  33 ++++++------
 7 files changed, 120 insertions(+), 75 deletions(-)

diff --git a/lg/members_en.txt b/lg/members_en.txt
index e6f6308..c7609eb 100755
--- a/lg/members_en.txt
+++ b/lg/members_en.txt
@@ -9,7 +9,8 @@ ORDER_BY in the following order
 ASC ascending
 DESC descending
 SUBMIT_BUTTON submit
-CHECKBOX_PENDING_SIGS Include pending certifications.
+CHECKBOX_PENDING_SIGS Include pending certifications
+CHECKBOX_MODE_SIG Print emitted certifications (Instead of received certifications)
 LEGEND_AVAILABILITY [availability : means this certification may already be written in the next block.]
 CURRENT_BLOCKCHAIN_TIME Current blockchain time
 TABLE_TITLE Members that will expire in less than
@@ -18,11 +19,15 @@ COL_UID uid
 COL_IDTY_WRITTEN_TIME identity written time
 COL_LAST_RENEWAL last renewal
 COL_EXPIRE_MEMBERSHIP expire membership
+COL_DISTANCE distance
+COL_DISTANCE_isOutdistanced KO
+COL_DISTANCE_isNotOutdistanced OK
 COL_LIST_RECEIVED_CERT list received certifications
 COL_LIST_EMITTED_CERT list emitted certifications
 LAST2OLDEST récentes -> anciennes
 OLDEST2LAST anciennes -> récentes
 EMITTED emitted
 WRITTEN written
+CERT_AVAILABLE available
 OVERALL Overall
 MEMBERS members
\ No newline at end of file
diff --git a/lg/members_fr.txt b/lg/members_fr.txt
index 83798b7..c2db83b 100755
--- a/lg/members_fr.txt
+++ b/lg/members_fr.txt
@@ -1,6 +1,6 @@
 FORM1 jours - tri par
 SORT_BY_IDTY_WRITTEN date d'obtention du statut de membre
-SORT_BY_EXPIRE_MEMBERSHIP date d\'expiration du membership
+SORT_BY_EXPIRE_MEMBERSHIP date d'expiration du membership
 SORT_LAST_RENEWAL date de dernier renouvellement
 SORT_BY_OLDEST_SIG date de plus vielle certification
 SORT_BY_LAST_SIG date de plus récente certification
@@ -9,7 +9,8 @@ ORDER_BY dans l'ordre
 ASC croissant
 DESC décroissant
 SUBMIT_BUTTON recharger
-CHECKBOX_PENDING_SIGS Inclure les certifications en piscine.
+CHECKBOX_PENDING_SIGS Inclure les certifications en piscine
+CHECKBOX_MODE_SIG Afficher les certifications émises (à la place des certifications reçus)
 LEGEND_AVAILABILITY [disponibilité : date à partir de laquelle cette certification pourra être écrite compte tenu de sigPeriod]
 CURRENT_BLOCKCHAIN_TIME Temps Blockchain actuel
 TABLE_TITLE Membres dont le statut de membre va expirer dans moins de
@@ -18,11 +19,15 @@ COL_UID uid
 COL_IDTY_WRITTEN_TIME obtention statut membre
 COL_LAST_RENEWAL dernier renouvellement
 COL_EXPIRE_MEMBERSHIP date d'expiration du membre
+COL_DISTANCE distance
+COL_DISTANCE_isOutdistanced KO
+COL_DISTANCE_isNotOutdistanced OK
 COL_LIST_RECEIVED_CERT liste des certifications reçues
-COL_LIST_EMMITED_CERT liste des certifications émises
+COL_LIST_EMITTED_CERT liste des certifications émises
 LAST2OLDEST récentes -> anciennes
 OLDEST2LAST anciennes -> récentes
 EMITTED émise
 WRITTEN écrite
+CERT_AVAILABLE disponible
 OVERALL Total
 MEMBERS membres
\ No newline at end of file
diff --git a/package.json b/package.json
index 5eb67f1..22ca8c5 100755
--- a/package.json
+++ b/package.json
@@ -20,13 +20,14 @@
     "rimraf": "^2.6.1",
     "tmp": "^0.0.31",
     "underscore": "1.8.3",
+    "wotb": "^0.6.2",
     "ws": "1.1.1"
   },
   "devDependencies": {
     "duniter": "1.3.9",
-    "duniter-keypair": "1.3.x",
     "duniter-bma": "1.3.x",
     "duniter-crawler": "1.3.x",
+    "duniter-keypair": "1.3.x",
     "duniter-prover": "1.3.x"
   },
   "peerDependencies": {
diff --git a/routes/members.js b/routes/members.js
index 043ce0f..de44f4f 100755
--- a/routes/members.js
+++ b/routes/members.js
@@ -1,6 +1,8 @@
 "use strict";
 
 const co = require('co')
+const wotb = require('wotb')
+
 const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
 module.exports = (req, res, next) => co(function *() {
@@ -8,16 +10,17 @@ module.exports = (req, res, next) => co(function *() {
   var { duniterServer, sigValidity, msValidity, sigWindow, idtyWindow, cache  } = req.app.locals
   
   try {
-    
-    // get blockchain timestamp
-    let resultQueryCurrentBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime` FROM block ORDER BY `medianTime` DESC LIMIT 1 ');
-    const currentBlockchainTimestamp = resultQueryCurrentBlock[0].medianTime;
+    // Initaliser les constantes
+    const conf = duniterServer.conf;
+    const head = yield duniterServer.dal.getCurrentBlockOrNull();
+    const currentBlockchainTimestamp =  head ? head.medianTime : 0;
+    const membersCount = head ? head.membersCount : 0;
+    const dSen = Math.ceil(Math.pow(membersCount, 1 / conf.stepMax));
     
     // Initaliser les variables
     var contenu = "";
     var membersIdentity = [];
     var membersFirstCertifExpire = [];
-    var membersIssuerFirstCertif = [];
     var membersCertifsList = [];
     var membersPendingCertifsList = [];
     var membershipsTimeList = [];
@@ -25,14 +28,18 @@ module.exports = (req, res, next) => co(function *() {
     var membershipsExpireTimeList = [];
     
     // Récupéré les paramètres
-    var days = req.query.d || 400// Valeur par défaut
+    var days = req.query.d || 400 // Valeur par défaut
+    var mode = req.query.mode || 'received' // Valeur par défaut
     var order = req.query.d && req.query.order || 'desc' // Valeur par défaut
     var sort_by = req.query.sort_by || "idtyWritten" // Valeur par défaut
     var pendingSigs = req.query.pendingSigs || "no";
     var format = req.query.format || 'HTML';
     
+    // Alimenter wotb avec la toile actuelle
+    const wotbInstance = wotb.newFileInstance(duniterServer.home + '/wotb.bin');
+    
     // Récupérer la liste des identités ayant actuellement le statut de membre
-    const membersList = yield duniterServer.dal.peerDAL.query('SELECT `uid`,`pub`,`member`,`written_on` FROM i_index WHERE `member`=1');
+    const membersList = yield duniterServer.dal.peerDAL.query('SELECT `uid`,`pub`,`member`,`written_on`,`wotb_id` FROM i_index WHERE `member`=1');
     
     // Récupérer pour chaque identité, le numéro du block d'écriture du dernier membership
     // Ainsi que la première ou dernière certification
@@ -55,34 +62,52 @@ module.exports = (req, res, next) => co(function *() {
       let resultQueryTimeWrittenIdty = yield duniterServer.dal.peerDAL.query(
           'SELECT `medianTime` FROM block WHERE `number`=\''+blockstampIdtyWritten[0]+'\' LIMIT 1')
       
+      // Tester la distance
+      let tmpWot = wotbInstance.memCopy();
+      //let tmpWot = duniterServer.dal.wotb.memCopy();
+
+      //let detailedDistance = tmpWot.detailedDistance(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent);
+      //let isOutdistanced = detailedDistance.isOutdistanced;
+      let isOutdistanced = tmpWot.isOutdistanced(membersList[m].wotb_id, dSen, conf.stepMax, conf.xpercent);
+      
       // Stocker les informations de l'identité
       membersIdentity.push({
         writtenBloc: blockstampIdtyWritten[0],
-        writtenTimestamp: resultQueryTimeWrittenIdty[0].medianTime
+        writtenTimestamp: resultQueryTimeWrittenIdty[0].medianTime,
+        isOutdistanced: isOutdistanced
         });
       
-      // récupérer toutes les certification  reçus par l'utilisateur
+      // récupérer toutes les certification  reçus/émises par l'utilisateur
       let tmpQueryCertifsList = [];
-      if (sort_by == "lastSig")
+      let tmpOrder = (sort_by == "lastSig") ? 'DESC' : 'ASC';
+      if (mode == 'emitted')
       {
         tmpQueryCertifsList = yield duniterServer.dal.peerDAL.query(
-          'SELECT `issuer`,`written_on`,`expires_on` FROM c_index WHERE `receiver`=\''+membersList[m].pub+'\' ORDER BY `expires_on` DESC');
+          'SELECT `receiver`,`written_on`,`expires_on` FROM c_index WHERE `issuer`=\''+membersList[m].pub+'\' ORDER BY `expires_on` '+tmpOrder);
       }
       else
       {
-        tmpQueryCertifsList = yield duniterServer.dal.peerDAL.query(
-          'SELECT `issuer`,`written_on`,`expires_on` FROM c_index WHERE `receiver`=\''+membersList[m].pub+'\' ORDER BY `expires_on` ASC');
+	tmpQueryCertifsList = yield duniterServer.dal.peerDAL.query(
+          'SELECT `issuer`,`written_on`,`expires_on` FROM c_index WHERE `receiver`=\''+membersList[m].pub+'\' ORDER BY `expires_on` '+tmpOrder);
       }
 
-      // Calculer le nombre de certifications reçus par le membre courant
+      // Calculer le nombre de certifications reçus/émises par le membre courant
       let nbWrittenCertifs = tmpQueryCertifsList.length;
       
-      // Récupérer les uid des émetteurs des certifications reçus par l'utilisateur
+      // Récupérer les uid des émetteurs/receveurs des certifications reçus/émises par l'utilisateur
       // Et stocker les uid et dates d'expiration dans un tableau
       membersCertifsList[m] = new Array();
       for (var i=0;i<nbWrittenCertifs;i++)
       {
-        let tmpQueryGetUidIssuerCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpQueryCertifsList[i].issuer+'\' LIMIT 1');
+	let tmpQueryGetUidProtagonistCert
+	if (mode == 'emitted')
+	{
+          tmpQueryGetUidProtagonistCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpQueryCertifsList[i].receiver+'\' LIMIT 1');
+	}
+	else
+	{
+          tmpQueryGetUidProtagonistCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpQueryCertifsList[i].issuer+'\' LIMIT 1');
+	}
         let tmpBlockWrittenOn = tmpQueryCertifsList[i].written_on.split("-");
         
         // Stoker la liste des certifications qui n'ont pas encore expirées
@@ -90,11 +115,11 @@ module.exports = (req, res, next) => co(function *() {
         {
           if (i == 0)
           {
-        membersIssuerFirstCertif.push(tmpQueryGetUidIssuerCert[0].uid);
-        membersFirstCertifExpire.push(tmpQueryCertifsList[0].expires_on);
+	    membersFirstCertifExpire.push(tmpQueryCertifsList[0].expires_on);
           }
           membersCertifsList[m].push({
-          issuer: tmpQueryGetUidIssuerCert[0].uid,
+          issuer: (mode=='emitted') ? membersList[m].uid:tmpQueryGetUidProtagonistCert[0].uid,
+	  receiver: (mode!='emitted') ? membersList[m].uid:tmpQueryGetUidProtagonistCert[0].uid,
           writtenBloc: tmpBlockWrittenOn[0],
           timestampExpire: tmpQueryCertifsList[i].expires_on
           });
@@ -103,19 +128,20 @@ module.exports = (req, res, next) => co(function *() {
       
       // SI LES CERTIFICATIONS EN PISCINE SONT DEMANDÉES
       let nbValidPendingCertifs = 0;
+      
       if (pendingSigs == "yes")
       {
-        // récupérer toutes les certification en piscine destinées à l'utilisateur
+        // récupérer toutes les certification en piscine
         let tmpQueryPendingCertifsList = [];
-        if (sort_by == "lastSig")
+        if (mode == 'emitted')
         {
           tmpQueryPendingCertifsList = yield duniterServer.dal.peerDAL.query(
-        'SELECT `from`,`block_number`,`expires_on` FROM certifications_pending WHERE `to`=\''+membersList[m].pub+'\' ORDER BY `expires_on` DESC');
+	    'SELECT `from`,`to`,`block_number`,`expires_on` FROM certifications_pending WHERE `from`=\''+membersList[m].pub+'\' ORDER BY `expires_on` '+tmpOrder);
         }
         else
         {
           tmpQueryPendingCertifsList = yield duniterServer.dal.peerDAL.query(
-        'SELECT `from`,`block_number`,`expires_on` FROM certifications_pending WHERE `to`=\''+membersList[m].pub+'\' ORDER BY `expires_on` ASC');
+	    'SELECT `from`,`block_number`,`expires_on` FROM certifications_pending WHERE `to`=\''+membersList[m].pub+'\' ORDER BY `expires_on` '+tmpOrder);
         }
         
         // Calculer le nombre de certifications en attentes destinées au membre courant
@@ -126,24 +152,26 @@ module.exports = (req, res, next) => co(function *() {
         membersPendingCertifsList[m] = new Array();
         for (var i=0;i<nbPendingCertifs;i++)
         {
-          let tmpQueryGetUidIssuerPendingCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpQueryPendingCertifsList[i].from+'\' LIMIT 1');
+	  let tmpPub = (mode=='emitted') ? tmpQueryPendingCertifsList[i].to:tmpQueryPendingCertifsList[i].from;
+          let tmpQueryGetUidProtagonistPendingCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpPub+'\' LIMIT 1');
+	  
           // Vérifier que l'émetteur de la certification correspond à une identié connue
-          if ( tmpQueryGetUidIssuerPendingCert.length > 0 )
+          if ( tmpQueryGetUidProtagonistPendingCert.length > 0 )
           {
-        // récupérer le timestamp d'écriture de la dernière certification écrite par l'émetteur
-        let tmpQueryLastIssuerCert = yield duniterServer.dal.peerDAL.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+tmpQueryPendingCertifsList[i].from+'\' ORDER BY `expires_on` DESC LIMIT 1');
-        
-        // Stoker la liste des certifications en piscine qui n'ont pas encore expirées
-        if (tmpQueryPendingCertifsList[i].expires_on > currentBlockchainTimestamp)
-        {
-          membersPendingCertifsList[m].push({
-              from: tmpQueryGetUidIssuerPendingCert[0].uid,
-              blockNumber: tmpQueryPendingCertifsList[i].block_number,
-              timestampExpire: tmpQueryPendingCertifsList[i].expires_on,
-              timestampWritable: (tmpQueryLastIssuerCert[0].chainable_on)
-          });
-          nbValidPendingCertifs++;
-        }
+	    // récupérer le timestamp d'écriture de la dernière certification écrite par l'émetteur
+	    let tmpQueryLastIssuerCert = yield duniterServer.dal.peerDAL.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+tmpQueryPendingCertifsList[i].from+'\' ORDER BY `expires_on` DESC LIMIT 1');
+	    
+	    // Stoker la liste des certifications en piscine qui n'ont pas encore expirées
+	    if (tmpQueryPendingCertifsList[i].expires_on > currentBlockchainTimestamp)
+	    {
+	      membersPendingCertifsList[m].push({
+		  protagonist: tmpQueryGetUidProtagonistPendingCert[0].uid,
+		  blockNumber: tmpQueryPendingCertifsList[i].block_number,
+		  timestampExpire: tmpQueryPendingCertifsList[i].expires_on,
+		  timestampWritable: (typeof(tmpQueryLastIssuerCert[0]) == 'undefined') ? 0:tmpQueryLastIssuerCert[0].chainable_on
+	      });
+	      nbValidPendingCertifs++;
+	    }
           }
         }
       }
@@ -168,8 +196,8 @@ module.exports = (req, res, next) => co(function *() {
     }
         
     // Initialiser le tableau membersListOrdered
-    var membersListOrdered = [ [] ];
-    var membersCertifsListSorted = [ [] ];
+    var membersListOrdered = [];
+    var membersCertifsListSorted = [];
 
     // Calculer le timestamp limite à prendre en compte
     var limitTimestamp = currentBlockchainTimestamp + (days*86400);
@@ -231,11 +259,13 @@ module.exports = (req, res, next) => co(function *() {
           lastRenewalWrittenBloc: membershipsBlockNumberList[idMaxTime],
           expireMembershipTimestamp: membershipsExpireTimeList[idMaxTime],
           certifications: membersCertifsList[idMaxTime],
-          pendingCertifications: membersPendingCertifsList[idMaxTime]
+          pendingCertifications: membersPendingCertifsList[idMaxTime],
+	  isOutdistanced: membersIdentity[idMaxTime].isOutdistanced
         });
         
         membersCertifsListSorted.push({
         issuer: membersCertifsList[idMaxTime].issuer,
+	receiver: membersCertifsList[idMaxTime].receiver,
         writtenBloc: membersCertifsList[idMaxTime].writtenBloc,
         timestampExpire: membersCertifsList[idMaxTime].timestampExpire
         });
@@ -257,7 +287,7 @@ module.exports = (req, res, next) => co(function *() {
       res.locals = {
 	host: req.headers.host.toString(),
         
-        days, sort_by, order,
+        days, mode, sort_by, order,
         pendingSigs,
         
         currentBlockchainTimestamp,
diff --git a/routes/willMembers.js b/routes/willMembers.js
index 6cc14b8..ea865b8 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -2,7 +2,7 @@
 
 const co = require('co')
 const crypto = require('crypto')
-//const wotb = require('wotb')
+const wotb = require('wotb')
 
 const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
@@ -56,8 +56,8 @@ module.exports = (req, res, next) => co(function *() {
       countMembersWithSigQtyValidCert = 0;
       lastUpgradeTime = Math.floor(Date.now() / 1000);
       
-      // Alimenter wotb avec la toile Ğ1
-      //const wotbInstance = wotb.newFileInstance(duniterServer.home + '/wotb.bin');
+      // Alimenter wotb avec la toile actuelle
+      const wotbInstance = wotb.newFileInstance(duniterServer.home + '/wotb.bin');
       
       // Récupérer la liste des identités en piscine
       const resultQueryIdtys = yield duniterServer.dal.peerDAL.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on` FROM identities_pending WHERE `member`=0');
@@ -282,20 +282,21 @@ module.exports = (req, res, next) => co(function *() {
 	  if (!doubloon)
 	  {
 	    // Tester la distance à l'aide des certifications disponibles
-	    //let wotb = wotbInstance.memCopy();
-	    let wotb = duniterServer.dal.wotb.memCopy();
+	    let tmpWot = wotbInstance.memCopy();
+	    //let tmpWot = duniterServer.dal.wotb.memCopy();
 
-	    let pendingIdtyWID = wotb.addNode()
+	    let pendingIdtyWID = tmpWot.addNode();
 	    for (const cert of idtysPendingCertifsList[idMax])
 	    {
-	      wotb.addLink(cert.wid, pendingIdtyWID)
+	      tmpWot.addLink(cert.wid, pendingIdtyWID);
 	    }
-	    let detailedDistance = wotb.detailedDistance(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent)
+	    let detailedDistance = tmpWot.detailedDistance(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent);
 	    let isOutdistanced = detailedDistance.isOutdistanced;
-
+	    //let isOutdistanced = tmpWot.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent);
+	    
 	    // Tester la présence de l'adhésion
 	    let membership = null
-	    const pendingMembershipsOfIdty = yield duniterServer.dal.msDAL.getPendingINOfTarget(identitiesList[idMax].hash)
+	    const pendingMembershipsOfIdty = yield duniterServer.dal.msDAL.getPendingINOfTarget(identitiesList[idMax].hash);
 	    for (const ms of pendingMembershipsOfIdty) {
 	      if (!membership && ms.expires_on > currentBlockchainTimestamp) {
 		membership = ms
@@ -303,7 +304,7 @@ module.exports = (req, res, next) => co(function *() {
 	    }
 
 	    // Nettoie la wot temporaire
-	    wotb.clear();
+	    tmpWot.clear();
 	    
 	    idtysListOrdered.push({
 	      uid: identitiesList[idMax].uid,
diff --git a/views/about.html b/views/about.html
index 6e98480..d69d04d 100755
--- a/views/about.html
+++ b/views/about.html
@@ -31,7 +31,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.11">module-0.2.11</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.12">module-0.2.12</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/c-geek">cgeek</a> (willMembers and wotex),<a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
diff --git a/views/members.html b/views/members.html
index b9472b5..b0de78d 100755
--- a/views/members.html
+++ b/views/members.html
@@ -27,16 +27,17 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
 <!-- Afficher le formulaire -->
 <input type="number" name="d" value="${days}"/>${LANG["FORM1"]} <select name="sort_by">
 <option name="sort_by" value ="idtyWritten">${LANG["SORT_BY_IDTY_WRITTEN"]}
-<option name="sort_by" value ="expireMembership" ${sort_by == 'expireMembership' ? 'selected' : ''}>${LANG["SORT_BY_EXPIRE_MEMBERSHIP"]} date d\'expiration du membership
-<option name="sort_by" value ="lastRenewal" ${sort_by == 'lastRenewal' ? 'selected' : ''}>${LANG["SORT_LAST_RENEWAL"]} date de dernier renouvellement
-<option name="sort_by" value ="oldestSig" ${sort_by == 'oldestSig' ? 'selected' : ''}>${LANG["SORT_BY_OLDEST_SIG"]} date de plus vielle certification
-<option name="sort_by" value ="lastSig" ${sort_by == 'lastSig' ? 'selected' : ''}>${LANG["SORT_BY_LAST_SIG"]} date de plus récente certification
-<option name="sort_by" value ="sigCount" ${sort_by == 'sigCount' ? 'selected' : ''}>${LANG["SORT_BY_SIG_COUNT"]} nombre de certifications reçues
+<option name="sort_by" value ="expireMembership" ${sort_by == 'expireMembership' ? 'selected' : ''}>${LANG["SORT_BY_EXPIRE_MEMBERSHIP"]}
+<option name="sort_by" value ="lastRenewal" ${sort_by == 'lastRenewal' ? 'selected' : ''}>${LANG["SORT_LAST_RENEWAL"]}
+<option name="sort_by" value ="oldestSig" ${sort_by == 'oldestSig' ? 'selected' : ''}>${LANG["SORT_BY_OLDEST_SIG"]}
+<option name="sort_by" value ="lastSig" ${sort_by == 'lastSig' ? 'selected' : ''}>${LANG["SORT_BY_LAST_SIG"]}
+<option name="sort_by" value ="sigCount" ${sort_by == 'sigCount' ? 'selected' : ''}>${LANG["SORT_BY_SIG_COUNT"]}
 </select> ${LANG["ORDER_BY"]} <select name="order">
 <option name="order" value ="asc"> ${LANG["ASC"]}
 <option name="order" value ="desc" ${order == 'desc' ? 'selected' : ''}> ${LANG["DESC"]}</select>
 <input type="submit" value="envoyer"><br>
-<input type="checkbox" name="pendingSigs" value="yes" ${pendingSigs == 'yes' ? 'checked' : ''}>${LANG["CHECKBOX_PENDING_SIGS"]}</form><br>
+<input type="checkbox" name="pendingSigs" value="yes" ${pendingSigs == 'yes' ? 'checked' : ''}>${LANG["CHECKBOX_PENDING_SIGS"]}.<br>
+<input type="checkbox" name="mode" value="emitted" ${mode == 'emitted' ? 'checked' : ''}>${LANG["CHECKBOX_MODE_SIG"]}.</form><br>
 
 <!-- Afficher la légende -->
 <br>
@@ -55,8 +56,9 @@ ${(pendingSigs == 'yes' && help != 'no') ? ` ${LANG["LEGEND_AVAILABILITY"]}<br>`
     <td align="center">${LANG["COL_IDTY_WRITTEN_TIME"]}</td>
     <td align="center">${LANG["COL_LAST_RENEWAL"]}</td>
     <td align="center">${LANG["COL_EXPIRE_MEMBERSHIP"]}</td>
+    <td align='center'>${LANG['COL_DISTANCE']}</td>
     <td style="background:#000000">-</td>
-    <td align="left" colspan="${nbMaxCertifs}">liste des certifications reçues (${sort_by == 'lastSig' ? LANG["LAST2OLDEST"] : LANG["OLDEST2LAST"]})</td>
+    <td align="left" colspan="${nbMaxCertifs}">${(mode=='emitted') ? LANG['COL_LIST_EMITTED_CERT']:LANG['COL_LIST_RECEIVED_CERT']} (${sort_by == 'lastSig' ? LANG["LAST2OLDEST"] : LANG["OLDEST2LAST"]})</td>
   </tr>
   
   ${membersListFiltered
@@ -65,27 +67,25 @@ ${(pendingSigs == 'yes' && help != 'no') ? ` ${LANG["LEGEND_AVAILABILITY"]}<br>`
       <tr>
         ${(member.proportion = proportion(member.expireMembershipTimestamp,msValidity,0,120),'')}
         <td align="center" style="background:hsla(${member.proportion}, 100%, 50%, 1)">
-        <!--<td align="center" style="background:#${color}">-->
           <h3>${member.uid}</h3>
           ->${member.certifications.length}
           ${pendingSigs == "yes" && member.pendingCertifications.length > 0 
             ? `(${member.pendingCertifications.length})` 
             : ''}
         </td>
-        <!--<td align="center" style="background:hsla(0, 0%, ${member.proportion}%, 1)">-->
         <td align="center" style="background:hsla(${member.proportion}, 100%, 50%, 1)">
-        <!--<td align="center" style="background:#${color}">-->
           ${timestampToDatetime(member.idtyWrittenTimestamp)}<br>
           #${member.idtyWrittenBloc}
         </td>
         <td align="center" style="background:hsla(${member.proportion}, 100%, 50%, 1)">
-        <!--<td align="center" style="background:#${color}">-->
           ${timestampToDatetime(member.lastRenewalTimestamp)}<br>
           #${member.lastRenewalWrittenBloc}
         </td>
         <td align="center" style="background:hsla(${member.proportion}, 100%, 50%, 1)">
-        <!--<td align="center" style="background:#${color}">-->
           ${timestampToDatetime(member.expireMembershipTimestamp)}</td>
+        <td align='center' style="background:hsla(${member.proportion}, 100%, 50%, 1)">
+          <span style="color: ${member.isOutdistanced ? 'red' : 'blue' }">${member.isOutdistanced ? LANG['COL_DISTANCE_isOutdistanced'] : LANG['COL_DISTANCE_isNotOutdistanced'] }</span>
+        </td>
         <td style="background:#000000">-</td>
   
         <!-- Printer les certifications en piscine -->
@@ -93,10 +93,13 @@ ${(pendingSigs == 'yes' && help != 'no') ? ` ${LANG["LEGEND_AVAILABILITY"]}<br>`
             member.pendingCertifications.map( certification=> `
               <!-- Printer la certification -->
               <td align="center" style="background:${color(certification.timestampExpire,sigWindow,200)})">
-                ${certification.from}<br>
+                ${certification.protagonist}<br>
                 ${timestampToDatetime(certification.timestampExpire)}<br>
                 ${LANG["EMITTED"]} #${certification.blockNumber}<br>
-                [inscriptible ${timestampToDatetime(certification.timestampWritable)}]
+                ${(certification.timestampWritable > currentBlockchainTimestamp) ? `<font color="DarkRed">[${timestampToDatetime(certification.timestampWritable)}
+		  `:`<font color="green">[${LANG["CERT_AVAILABLE"]}`
+                }]
+                </font>
               </td>
             `).join('') 
         :''}
@@ -105,7 +108,7 @@ ${(pendingSigs == 'yes' && help != 'no') ? ` ${LANG["LEGEND_AVAILABILITY"]}<br>`
         ${member.certifications.map( certification=> `
           <!-- Printer la certification -->
           <td align="center" style="background:hsla(${proportion(certification.timestampExpire,sigValidity,0,120)}, 100%, 50%, 1 )">
-            ${certification.issuer}<br>
+            ${(mode=='emitted') ? certification.receiver:certification.issuer}<br>
             ${timestampToDatetime(certification.timestampExpire)}<br>
             ${LANG["WRITTEN"]} #${certification.writtenBloc}
           </td>
-- 
GitLab


From 965d5e81cb522c895ba303ba6fb6a45072c98661 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Fri, 30 Jun 2017 19:17:28 +0200
Subject: [PATCH 48/48] [fix] suppr wotb module

---
 package.json          |  1 -
 routes/members.js     |  8 ++++----
 routes/willMembers.js | 14 +++++++-------
 views/about.html      |  2 +-
 4 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/package.json b/package.json
index 22ca8c5..913d205 100755
--- a/package.json
+++ b/package.json
@@ -20,7 +20,6 @@
     "rimraf": "^2.6.1",
     "tmp": "^0.0.31",
     "underscore": "1.8.3",
-    "wotb": "^0.6.2",
     "ws": "1.1.1"
   },
   "devDependencies": {
diff --git a/routes/members.js b/routes/members.js
index de44f4f..0e566ff 100755
--- a/routes/members.js
+++ b/routes/members.js
@@ -1,7 +1,7 @@
 "use strict";
 
 const co = require('co')
-const wotb = require('wotb')
+//const wotb = require('wotb')
 
 const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
@@ -36,7 +36,7 @@ module.exports = (req, res, next) => co(function *() {
     var format = req.query.format || 'HTML';
     
     // Alimenter wotb avec la toile actuelle
-    const wotbInstance = wotb.newFileInstance(duniterServer.home + '/wotb.bin');
+    //const wotbInstance = wotb.newFileInstance(duniterServer.home + '/wotb.bin');
     
     // Récupérer la liste des identités ayant actuellement le statut de membre
     const membersList = yield duniterServer.dal.peerDAL.query('SELECT `uid`,`pub`,`member`,`written_on`,`wotb_id` FROM i_index WHERE `member`=1');
@@ -63,8 +63,8 @@ module.exports = (req, res, next) => co(function *() {
           'SELECT `medianTime` FROM block WHERE `number`=\''+blockstampIdtyWritten[0]+'\' LIMIT 1')
       
       // Tester la distance
-      let tmpWot = wotbInstance.memCopy();
-      //let tmpWot = duniterServer.dal.wotb.memCopy();
+      //let tmpWot = wotbInstance.memCopy();
+      let tmpWot = duniterServer.dal.wotb.memCopy();
 
       //let detailedDistance = tmpWot.detailedDistance(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent);
       //let isOutdistanced = detailedDistance.isOutdistanced;
diff --git a/routes/willMembers.js b/routes/willMembers.js
index ea865b8..be963cd 100755
--- a/routes/willMembers.js
+++ b/routes/willMembers.js
@@ -2,7 +2,7 @@
 
 const co = require('co')
 const crypto = require('crypto')
-const wotb = require('wotb')
+//const wotb = require('wotb')
 
 const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
 
@@ -57,7 +57,7 @@ module.exports = (req, res, next) => co(function *() {
       lastUpgradeTime = Math.floor(Date.now() / 1000);
       
       // Alimenter wotb avec la toile actuelle
-      const wotbInstance = wotb.newFileInstance(duniterServer.home + '/wotb.bin');
+      //const wotbInstance = wotb.newFileInstance(duniterServer.home + '/wotb.bin');
       
       // Récupérer la liste des identités en piscine
       const resultQueryIdtys = yield duniterServer.dal.peerDAL.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on` FROM identities_pending WHERE `member`=0');
@@ -282,17 +282,17 @@ module.exports = (req, res, next) => co(function *() {
 	  if (!doubloon)
 	  {
 	    // Tester la distance à l'aide des certifications disponibles
-	    let tmpWot = wotbInstance.memCopy();
-	    //let tmpWot = duniterServer.dal.wotb.memCopy();
+	    //let tmpWot = wotbInstance.memCopy();
+	    let tmpWot = duniterServer.dal.wotb.memCopy();
 
 	    let pendingIdtyWID = tmpWot.addNode();
 	    for (const cert of idtysPendingCertifsList[idMax])
 	    {
 	      tmpWot.addLink(cert.wid, pendingIdtyWID);
 	    }
-	    let detailedDistance = tmpWot.detailedDistance(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent);
-	    let isOutdistanced = detailedDistance.isOutdistanced;
-	    //let isOutdistanced = tmpWot.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent);
+	    //let detailedDistance = tmpWot.detailedDistance(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent);
+	    //let isOutdistanced = detailedDistance.isOutdistanced;
+	    let isOutdistanced = tmpWot.isOutdistanced(pendingIdtyWID, dSen, conf.stepMax, conf.xpercent);
 	    
 	    // Tester la présence de l'adhésion
 	    let membership = null
diff --git a/views/about.html b/views/about.html
index d69d04d..0b8d955 100755
--- a/views/about.html
+++ b/views/about.html
@@ -31,7 +31,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
   <a href="https://github.com/duniter/duniter-currency-monit/blob/master/LICENSE">License AGPL V 3.0</a><br>
   <a href="https://github.com/duniter/duniter-currency-monit/">github repository</a>
 </div><br>
-<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.12">module-0.2.12</a></div><br>
+<div align="left">Version : <a href="https://github.com/duniter/duniter-currency-monit/releases/tag/module-0.2.13">module-0.2.13</a></div><br>
 <div align="left">Author : <a href="https://github.com/librelois">Éloïs Librelois</a></div><br>
 <div align="left">Contributors : <a href="https://github.com/jytou">jytou</a> (translator), <a href="https://github.com/devingfx">devingfx</a> (frontend), <a href="https://github.com/c-geek">cgeek</a> (willMembers and wotex),<a href="https://github.com/M5oul">M5oul</a> (adjustments)</div><br>
 <br>
-- 
GitLab