diff --git a/app/lib/common-libs/underscore.ts b/app/lib/common-libs/underscore.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4bb08092d66a51db4d01a4733a97214086fdeae8
--- /dev/null
+++ b/app/lib/common-libs/underscore.ts
@@ -0,0 +1,28 @@
+const _ = require("underscore")
+
+export const Underscore = {
+
+  filter: <T>(elements:T[], filterFunc: (t:T) => boolean): T[] => {
+    return _.filter(elements, filterFunc)
+  },
+
+  where: <T>(elements:T[], props: { [k in keyof T]?: T[k] }): T[] => {
+    return _.where(elements, props)
+  },
+
+  keys: <T>(map:T): (keyof T)[] => {
+    return _.keys(map)
+  },
+
+  values: <T>(map:{ [k:string]: T }): T[] => {
+    return _.values(map)
+  },
+
+  pluck: <T, K extends keyof T>(elements:T[], k:K): T[K][] => {
+    return _.pluck(elements, k)
+  },
+
+  uniq: <T>(elements:T[]): T[] => {
+    return _.uniq(elements)
+  }
+}
diff --git a/app/lib/computation/QuickSync.ts b/app/lib/computation/QuickSync.ts
index 0c142ef097742beccc52535875cb7cece57c5c77..b825912f7b4113adbb6c0dfa427e31d7371cacd6 100644
--- a/app/lib/computation/QuickSync.ts
+++ b/app/lib/computation/QuickSync.ts
@@ -43,7 +43,7 @@ const sync_memoryDAL:AccountsGarbagingDAL = {
     }
   },
   sindexDAL: {
-    getAvailableForConditions: (conditions:string) => null
+    getAvailableForConditions: (conditions:string) => Promise.resolve([])
   }
 }
 
@@ -100,7 +100,9 @@ export class QuickSynchronizer {
 
   async quickApplyBlocks(blocks:BlockDTO[], to: number): Promise<void> {
 
-    sync_memoryDAL.sindexDAL = { getAvailableForConditions: (conditions:string) => this.dal.sindexDAL.getAvailableForConditions(conditions) }
+    sync_memoryDAL.sindexDAL = {
+      getAvailableForConditions: (conditions:string) => this.dal.sindexDAL.getAvailableForConditions(conditions)
+    }
 
     await this.dal.blockDAL.insertBatch(blocks.map((b:any) => {
       const block = DBBlock.fromBlockDTO(b)
diff --git a/app/lib/dal/indexDAL/abstract/IIndexDAO.ts b/app/lib/dal/indexDAL/abstract/IIndexDAO.ts
index d85975ce3a87affd9a6128cdac574e6750e11a15..ac4e52b4592baf44069d3d374caaa773c7d132d4 100644
--- a/app/lib/dal/indexDAL/abstract/IIndexDAO.ts
+++ b/app/lib/dal/indexDAL/abstract/IIndexDAO.ts
@@ -1,6 +1,6 @@
 import {FullIindexEntry, IindexEntry} from "../../../indexer"
 import {ReduceableDAO} from "./ReduceableDAO"
-import {OldIindexEntry} from "../../sqliteDAL/index/IIndexDAL"
+import {OldIindexEntry} from "../../../db/OldIindexEntry"
 
 export interface IIndexDAO extends ReduceableDAO<IindexEntry> {
 
diff --git a/app/lib/dal/indexDAL/abstract/SIndexDAO.ts b/app/lib/dal/indexDAL/abstract/SIndexDAO.ts
index a740299f9b23a9447e5546f0ca19c8b2fe775f05..8f96f4ba51d41c050e966b4ea540778ce706abce 100644
--- a/app/lib/dal/indexDAL/abstract/SIndexDAO.ts
+++ b/app/lib/dal/indexDAL/abstract/SIndexDAO.ts
@@ -11,7 +11,7 @@ export interface SIndexDAO extends ReduceableDAO<SindexEntry> {
 
   getAvailableForPubkey(pubkey:string): Promise<{ amount:number, base:number }[]>
 
-  getAvailableForConditions(conditionsStr:string): Promise<{ amount:number, base:number }[]>
+  getAvailableForConditions(conditionsStr:string): Promise<SindexEntry[]>
 
   trimConsumedSource(belowNumber:number): Promise<void>
 
diff --git a/app/lib/dal/indexDAL/loki/LokiCIndex.ts b/app/lib/dal/indexDAL/loki/LokiCIndex.ts
index 077041a9030be105bba6f2689b5dd1cdee7f080b..789ac77df3dd44d76be3a6d011ea5455bc3d31d8 100644
--- a/app/lib/dal/indexDAL/loki/LokiCIndex.ts
+++ b/app/lib/dal/indexDAL/loki/LokiCIndex.ts
@@ -10,7 +10,7 @@ export class LokiCIndex extends LokiIndex<CindexEntry> implements CIndexDAO {
   }
 
   async existsNonReplayableLink(issuer: string, receiver: string): Promise<boolean> {
-    return Indexer.DUP_HELPERS.reduceTyped<CindexEntry>(
+    return Indexer.DUP_HELPERS.reduce<CindexEntry>(
       this.collection
         .chain()
         .find({
diff --git a/app/lib/dal/indexDAL/loki/LokiIIndex.ts b/app/lib/dal/indexDAL/loki/LokiIIndex.ts
index e8576214c6d6d558c6a0f6dace7d295c38add5dc..8124c1bdbb0d2fbdbb6d2007e5903115dcfba734 100644
--- a/app/lib/dal/indexDAL/loki/LokiIIndex.ts
+++ b/app/lib/dal/indexDAL/loki/LokiIIndex.ts
@@ -1,9 +1,9 @@
 import {FullIindexEntry, IindexEntry, Indexer} from "../../../indexer"
 import {IIndexDAO} from "../abstract/IIndexDAO"
-import {OldIindexEntry} from "../../sqliteDAL/index/IIndexDAL"
 import {LokiPubkeySharingIndex} from "./LokiPubkeySharingIndex"
 import {getDurationInMicroSeconds, getMicrosecondsTime} from "../../../../ProcessCpuProfiler"
 import {NewLogger} from "../../../logger"
+import {OldIindexEntry} from "../../../db/OldIindexEntry"
 
 export class LokiIIndex extends LokiPubkeySharingIndex<IindexEntry> implements IIndexDAO {
 
diff --git a/app/lib/dal/indexDAL/loki/LokiMIndex.ts b/app/lib/dal/indexDAL/loki/LokiMIndex.ts
index 9be6232def85164740d76c6adb1f2e8a4fbf9db0..5ab94e90c3ebf4644056be693d819f7509fb633c 100644
--- a/app/lib/dal/indexDAL/loki/LokiMIndex.ts
+++ b/app/lib/dal/indexDAL/loki/LokiMIndex.ts
@@ -39,7 +39,7 @@ export class LokiMIndex extends LokiPubkeySharingIndex<MindexEntry> implements M
   }
 
   async getReducedMS(pub: string): Promise<FullMindexEntry | null> {
-    const reducable = await this.reducable(pub)
+    const reducable = (await this.reducable(pub)) as (FullMindexEntry)[]
     if (reducable.length) {
       return Indexer.DUP_HELPERS.reduce(reducable)
     }
diff --git a/app/lib/dal/indexDAL/loki/LokiSIndex.ts b/app/lib/dal/indexDAL/loki/LokiSIndex.ts
index 3a8a795f84dc98293e366127a0c0c9fe2c9b41a7..d7d6bb288cc8432baf0433d3aadfa1927a287947 100644
--- a/app/lib/dal/indexDAL/loki/LokiSIndex.ts
+++ b/app/lib/dal/indexDAL/loki/LokiSIndex.ts
@@ -22,7 +22,7 @@ export class LokiSIndex extends LokiIndex<SindexEntry> implements SIndexDAO {
       })
   }
 
-  async getAvailableForConditions(conditionsStr: string): Promise<{ amount: number; base: number }[]> {
+  async getAvailableForConditions(conditionsStr: string): Promise<SindexEntry[]> {
     const sources = this.collection
       .chain()
       .find({ conditions: { $regex: conditionsStr } })
diff --git a/app/lib/dal/sqliteDAL/AbstractIndex.ts b/app/lib/dal/sqliteDAL/AbstractIndex.ts
deleted file mode 100644
index 298295be161751372f971eb068d046f45fe3b531..0000000000000000000000000000000000000000
--- a/app/lib/dal/sqliteDAL/AbstractIndex.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
-// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU Affero General Public License for more details.
-
-import {AbstractSQLite, BeforeSaveHook} from "./AbstractSQLite";
-import {SQLiteDriver} from "../drivers/SQLiteDriver";
-import {IndexEntry, Indexer} from "../../indexer";
-
-const _ = require('underscore');
-
-export class AbstractIndex<T extends IndexEntry> extends AbstractSQLite<T> {
-
-  constructor(
-    driver:SQLiteDriver,
-    table: string,
-    pkFields: string[] = [],
-    fields: string[] = [],
-    arrays: string[] = [],
-    booleans: string[] = [],
-    bigintegers: string[] = [],
-    transientFields: string[] = [],
-    beforeSaveHook: BeforeSaveHook<T> | null = null
-  ) {
-    super(driver, table, pkFields, fields, arrays, booleans, bigintegers, transientFields, beforeSaveHook)
-  }
-
-  public async init() {}
-
-  getWrittenOn(blockstamp:string) {
-    return this.query('SELECT * FROM ' + this.table + ' WHERE written_on = ?', [blockstamp])
-  }
-
-  async trimRecords(belowNumber:number) {
-    const belowRecords:T[] = await this.query('SELECT COUNT(*) as nbRecords, pub FROM ' + this.table + ' ' +
-      'WHERE CAST(written_on as int) < ? ' +
-      'GROUP BY pub ' +
-      'HAVING nbRecords > 1', [belowNumber]);
-    const reducedByPub = Indexer.DUP_HELPERS.reduceBy(belowRecords, ['pub']);
-    for (const record of reducedByPub) {
-      const recordsOfPub = await this.query('SELECT * FROM ' + this.table + ' WHERE pub = ?', [record.pub]);
-      const toReduce = _.filter(recordsOfPub, (rec:T) => parseInt(rec.written_on) < belowNumber);
-      if (toReduce.length) {
-        // Clean the records in the DB
-        await this.exec('DELETE FROM ' + this.table + ' WHERE pub = \'' + record.pub + '\'');
-        const nonReduced = _.filter(recordsOfPub, (rec:T) => parseInt(rec.written_on) >= belowNumber);
-        const reduced = Indexer.DUP_HELPERS.reduce(toReduce);
-        // Persist
-        await this.insertBatch([reduced].concat(nonReduced));
-      }
-    }
-  }
-}
diff --git a/app/lib/dal/sqliteDAL/MetaDAL.ts b/app/lib/dal/sqliteDAL/MetaDAL.ts
index 2ca460cd8d6d9a0889ba94b5768d3492785ffe0b..023259da4cd28cfb28da618488320e8f8d05b279 100644
--- a/app/lib/dal/sqliteDAL/MetaDAL.ts
+++ b/app/lib/dal/sqliteDAL/MetaDAL.ts
@@ -14,15 +14,8 @@
 import {AbstractSQLite} from "./AbstractSQLite"
 import {SQLiteDriver} from "../drivers/SQLiteDriver"
 import {ConfDTO} from "../../dto/ConfDTO"
-import {SindexEntry} from "../../indexer"
-import {hashf} from "../../common"
 import {TransactionDTO} from "../../dto/TransactionDTO"
 import {IdentityDAL} from "./IdentityDAL"
-import {SIndexDAL} from "./index/SIndexDAL"
-import {DBBlock} from "../../db/DBBlock"
-import {IdentityDTO} from "../../dto/IdentityDTO"
-import {rawer} from "../../common-libs/index"
-import {CommonConstants} from "../../common-libs/constants"
 
 const _ = require('underscore')
 const logger = require('../../logger').NewLogger('metaDAL');
@@ -207,156 +200,7 @@ export class MetaDAL extends AbstractSQLite<DBMeta> {
     16: async () => {},
 
     17: async () => {
-      let blockDAL:any = new MetaDAL(this.driverCopy)
-      let sindexDAL = new SIndexDAL(this.driverCopy)
-      const blocks = await blockDAL.query('SELECT * FROM block WHERE NOT fork');
-      type AmountPerKey = {
-        amounts: {
-          amount: number
-          comment:string
-        }[],
-        sources: {
-          amount:number
-          base:number
-          identifier:string
-          pos:number,
-          conditions:string
-          block:DBBlock,
-          tx:string|null
-        }[]
-      }
-      const amountsPerKey:{ [pub:string]: AmountPerKey[] } = {}
-      const members = [];
-      for (const b of blocks) {
-        const amountsInForBlockPerKey: { [pub:string]: AmountPerKey } = {};
-        for (const idty of b.identities) {
-          members.push(IdentityDTO.fromInline(idty).pubkey)
-        }
-        if (b.dividend) {
-          for (const member of members) {
-            amountsInForBlockPerKey[member] = amountsInForBlockPerKey[member] || { amounts: [], sources: [] };
-            amountsInForBlockPerKey[member].amounts.push({ amount: b.dividend * Math.pow(10, b.unitbase), comment: 'Dividend' });
-            amountsInForBlockPerKey[member].sources.push({ amount: b.dividend, base: b.unitbase, identifier: member, pos: b.number, block: b, tx: null, conditions: 'SIG(' + member + ')' });
-          }
-        }
-        const txs = b.transactions
-        for (let i = 0; i < txs.length; i++) {
-          const tx = txs[i];
-          tx.hash = hashf(rawer.getTransaction(b.transactions[i]))
-          for (const input of tx.inputsAsObjects()) {
-            amountsInForBlockPerKey[tx.issuers[0]] = amountsInForBlockPerKey[tx.issuers[0]] || { amounts: [], sources: [] };
-            amountsInForBlockPerKey[tx.issuers[0]].amounts.push({ amount: -input.amount * Math.pow(10, input.base), comment: tx.comment || '######' });
-            amountsInForBlockPerKey[tx.issuers[0]].sources.push({
-              amount: input.amount,
-              base: input.base,
-              identifier: input.identifier,
-              pos: input.pos,
-              conditions: "",
-              block: b,
-              tx: tx.hash
-            })
-          }
-          const outputObjects = tx.outputsAsObjects()
-          for (let j = 0; j < outputObjects.length; j++) {
-            const output = outputObjects[j]
-            const conditions = output.conditions.match(/^SIG\((.+)\)$/);
-            if (conditions) {
-              amountsInForBlockPerKey[conditions[1]] = amountsInForBlockPerKey[conditions[1]] || { amounts: [], sources: [] };
-              amountsInForBlockPerKey[conditions[1]].amounts.push({ amount: output.amount * Math.pow(10, output.base), comment: tx.comment || '######' });
-              amountsInForBlockPerKey[conditions[1]].sources.push({
-                amount: output.amount,
-                base: output.base,
-                identifier: tx.hash,
-                pos: j,
-                conditions: output.conditions,
-                block: b,
-                tx: tx.hash
-              })
-            }
-          }
-        }
-        for (const key of Object.keys(amountsInForBlockPerKey)) {
-          amountsPerKey[key] = amountsPerKey[key] || [];
-          amountsPerKey[key].push(amountsInForBlockPerKey[key]);
-        }
-      }
-      const keysToSee = Object.keys(amountsPerKey);
-      const sourcesMovements: SindexEntry[] = [];
-      for (const key of keysToSee) {
-        const allCreates: any = {};
-        const allUpdates: any = {};
-        const amounts = amountsPerKey[key];
-        let balance = 0;
-        for (let j = 0; j < amounts.length; j++) {
-          const amountsInBlock = amounts[j].amounts;
-          for (let i = 0; i < amountsInBlock.length; i++) {
-            const a = amountsInBlock[i].amount;
-            const id = [amounts[j].sources[i].identifier, amounts[j].sources[i].pos].join('-');
-            if (a < 0) {
-              allUpdates[id] = amounts[j].sources[i];
-              delete allCreates[id];
-            } else {
-              allCreates[id] = amounts[j].sources[i];
-            }
-            balance += a;
-          }
-          if (balance > 0 && balance < 100) {
-            const sourcesToDelete = [];
-            for (const k of Object.keys(amountsPerKey)) {
-              for (const packet of amountsPerKey[k]) {
-                for (const src of packet.sources) {
-                  const id = [src.identifier, src.pos].join('-');
-                  if (src.conditions == 'SIG(' + key + ')' && allCreates[id]) {
-                    sourcesToDelete.push(src);
-                  }
-                }
-              }
-            }
-            const amountsToDelete = sourcesToDelete.map((src) => {
-              return {
-                amount: -src.amount * Math.pow(10, src.base),
-                comment: '--DESTRUCTION--'
-              };
-            });
-            amounts.splice(j + 1, 0, { amounts: amountsToDelete, sources: sourcesToDelete });
-          }
-        }
-        let amountMissing = 0;
-        await Promise.all(_.values(allCreates).map(async (src:any) => {
-          const exist = await sindexDAL.getSource(src.identifier, src.pos);
-          if (!exist || exist.consumed) {
-            amountMissing += src.amount;
-            const block = src.block;
-            sourcesMovements.push({
-              index: CommonConstants.I_INDEX,
-              op: CommonConstants.IDX_CREATE,
-              tx: src.tx,
-              identifier: src.identifier,
-              pos: src.pos,
-              unlock: null,
-              age: 0,
-              txObj: TransactionDTO.mock(),
-              created_on: null,
-              written_on: [block.number, block.hash].join('-'),
-              writtenOn: block.number,
-              written_time: block.medianTime,
-              locktime: src.locktime,
-              amount: src.amount,
-              base: src.base,
-              conditions: src.conditions,
-              consumed: false
-            });
-          }
-        }))
-        let amountNotDestroyed = 0;
-        await Promise.all(_.values(allUpdates).map(async (src:any) => {
-          const exist = await sindexDAL.getSource(src.identifier, src.pos);
-          if (exist && !exist.consumed) {
-            amountNotDestroyed += src.amount;
-          }
-        }))
-      }
-      await sindexDAL.insertBatch(sourcesMovements);
+      // This migration is now obsolete
     },
 
     18: 'BEGIN;' +
diff --git a/app/lib/dal/sqliteDAL/index/CIndexDAL.ts b/app/lib/dal/sqliteDAL/index/CIndexDAL.ts
deleted file mode 100644
index d0c58259a37ae6cc151f61cc5921f40c8e6649fe..0000000000000000000000000000000000000000
--- a/app/lib/dal/sqliteDAL/index/CIndexDAL.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
-// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU Affero General Public License for more details.
-
-import {AbstractIndex} from "../AbstractIndex"
-import {SQLiteDriver} from "../../drivers/SQLiteDriver"
-import {CindexEntry} from "../../../indexer"
-import {CommonConstants} from "../../../common-libs/constants"
-
-const constants = require('./../../../constants');
-const indexer         = require('../../../indexer').Indexer
-
-export class CIndexDAL extends AbstractIndex<CindexEntry> {
-
-  constructor(driver:SQLiteDriver) {
-    super(
-      driver,
-      'c_index',
-      // PK fields
-      ['op', 'issuer', 'receiver', 'written_on'],
-      // Fields
-      [
-        'op',
-        'issuer',
-        'receiver',
-        'created_on',
-        'written_on',
-        'writtenOn',
-        'sig',
-        'expires_on',
-        'expired_on',
-        'chainable_on',
-        'from_wid',
-        'to_wid'
-      ],
-      // Arrays
-      [],
-      // Booleans
-      [],
-      // BigIntegers
-      [],
-      // Transient
-      []
-    )
-  }
-
-  async init() {
-    await this.exec('BEGIN;' +
-      'CREATE TABLE IF NOT EXISTS ' + this.table + ' (' +
-      'op VARCHAR(10) NOT NULL,' +
-      'issuer VARCHAR(50) NOT NULL,' +
-      'receiver VARCHAR(50) NOT NULL,' +
-      'created_on VARCHAR(80) NOT NULL,' +
-      'written_on VARCHAR(80) NOT NULL,' +
-      'sig VARCHAR(100) NULL,' +
-      'expires_on INTEGER NULL,' +
-      'expired_on INTEGER NULL,' +
-      'chainable_on INTEGER NULL,' +
-      'from_wid INTEGER NULL,' +
-      'to_wid INTEGER NULL,' +
-      'PRIMARY KEY (op,issuer,receiver,written_on)' +
-      ');' +
-      'CREATE INDEX IF NOT EXISTS idx_cindex_issuer ON c_index (issuer);' +
-      'CREATE INDEX IF NOT EXISTS idx_cindex_receiver ON c_index (receiver);' +
-      'CREATE INDEX IF NOT EXISTS idx_cindex_chainable_on ON c_index (chainable_on);' +
-      'COMMIT;')
-  }
-
-  async reducablesFrom(from:string) {
-    const reducables = await this.query('SELECT * FROM ' + this.table + ' WHERE issuer = ? ORDER BY CAST(written_on as integer) ASC', [from]);
-    return indexer.DUP_HELPERS.reduceBy(reducables, ['issuer', 'receiver', 'created_on']);
-  }
-
-  async trimExpiredCerts(belowNumber:number) {
-    const toDelete = await this.query('SELECT * FROM ' + this.table + ' WHERE expired_on > ? AND CAST(written_on as int) < ?', [0, belowNumber])
-    for (const row of toDelete) {
-      await this.exec("DELETE FROM " + this.table + " " +
-        "WHERE issuer like '" + row.issuer + "' " +
-        "AND receiver = '" + row.receiver + "' " +
-        "AND created_on like '" + row.created_on + "'");
-    }
-  }
-
-  getWrittenOn(blockstamp:string) {
-    return this.sqlFind({ written_on: blockstamp })
-  }
-
-  findExpired(medianTime:number) {
-    return this.query('SELECT * FROM ' + this.table + ' c1 WHERE expires_on <= ? ' +
-      'AND NOT EXISTS (' +
-      ' SELECT * FROM c_index c2' +
-      ' WHERE c1.issuer = c2.issuer' +
-      ' AND c1.receiver = c2.receiver' +
-      ' AND c1.created_on = c2.created_on' +
-      ' AND c2.op = ?' +
-      ')', [medianTime, CommonConstants.IDX_UPDATE])
-  }
-
-  getValidLinksTo(receiver:string) {
-    return this.query('SELECT * FROM ' + this.table + ' c1 ' +
-      'WHERE c1.receiver = ? ' +
-      'AND c1.expired_on = 0 ' +
-      'AND NOT EXISTS (' +
-      ' SELECT * FROM c_index c2' +
-      ' WHERE c1.issuer = c2.issuer' +
-      ' AND c1.receiver = c2.receiver' +
-      ' AND c1.created_on = c2.created_on' +
-      ' AND c2.op = ?' +
-      ')', [receiver, CommonConstants.IDX_UPDATE])
-  }
-
-  getValidLinksFrom(issuer:string) {
-    return this.query('SELECT * FROM ' + this.table + ' c1 ' +
-      'WHERE c1.issuer = ? ' +
-      'AND c1.expired_on = 0 ' +
-      'AND NOT EXISTS (' +
-      ' SELECT * FROM c_index c2' +
-      ' WHERE c1.issuer = c2.issuer' +
-      ' AND c1.receiver = c2.receiver' +
-      ' AND c1.created_on = c2.created_on' +
-      ' AND c2.op = ?' +
-      ')', [issuer, CommonConstants.IDX_UPDATE])
-  }
-
-  async existsNonReplayableLink(issuer:string, receiver:string) {
-    const results = await this.query('SELECT * FROM ' + this.table + ' c1 ' +
-      'WHERE c1.issuer = ? ' +
-      'AND c1.receiver = ? ' +
-      'AND NOT EXISTS (' +
-      ' SELECT * FROM c_index c2' +
-      ' WHERE c1.issuer = c2.issuer' +
-      ' AND c1.receiver = c2.receiver' +
-      ' AND c1.created_on = c2.created_on' +
-      ' AND c2.op = ?' +
-      ')', [issuer, receiver, CommonConstants.IDX_UPDATE]);
-    return results.length > 0;
-  }
-
-  removeBlock(blockstamp:string) {
-    return this.exec('DELETE FROM ' + this.table + ' WHERE written_on = \'' + blockstamp + '\'')
-  }
-}
diff --git a/app/lib/dal/sqliteDAL/index/IIndexDAL.ts b/app/lib/dal/sqliteDAL/index/IIndexDAL.ts
deleted file mode 100644
index 12c6391fb7662eeed4c163e6591956991cc08901..0000000000000000000000000000000000000000
--- a/app/lib/dal/sqliteDAL/index/IIndexDAL.ts
+++ /dev/null
@@ -1,198 +0,0 @@
-// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
-// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU Affero General Public License for more details.
-
-import {SQLiteDriver} from "../../drivers/SQLiteDriver";
-import {AbstractIndex} from "../AbstractIndex";
-import {FullIindexEntry, IindexEntry, Indexer} from "../../../indexer";
-
-const _ = require('underscore');
-
-export interface OldIindexEntry extends IindexEntry {
-  pubkey: string
-  buid: string | null
-  revocation_sig:string | null
-}
-
-export class IIndexDAL extends AbstractIndex<IindexEntry> {
-
-  constructor(driver:SQLiteDriver) {
-    super(
-      driver,
-      'i_index',
-      // PK fields
-      ['op', 'pub', 'created_on', 'written_on'],
-      // Fields
-      [
-        'op',
-        'uid',
-        'pub',
-        'hash',
-        'sig',
-        'created_on',
-        'written_on',
-        'writtenOn',
-        'member',
-        'wasMember',
-        'kick',
-        'wotb_id'
-      ],
-      // Arrays
-      [],
-      // Booleans
-      ['member', 'wasMember', 'kick'],
-      // BigIntegers
-      [],
-      // Transient
-      []
-    )
-  }
-
-  init() {
-    return this.exec('BEGIN;' +
-      'CREATE TABLE IF NOT EXISTS ' + this.table + ' (' +
-      'op VARCHAR(10) NOT NULL,' +
-      'uid VARCHAR(100) NULL,' +
-      'pub VARCHAR(50) NOT NULL,' +
-      'hash VARCHAR(80) NULL,' +
-      'sig VARCHAR(80) NULL,' +
-      'created_on VARCHAR(80) NULL,' +
-      'written_on VARCHAR(80) NOT NULL,' +
-      'member BOOLEAN NULL,' +
-      'wasMember BOOLEAN NULL,' +
-      'kick BOOLEAN NULL,' +
-      'wotb_id INTEGER NULL,' +
-      'PRIMARY KEY (op,pub,created_on,written_on)' +
-      ');' +
-      'CREATE INDEX IF NOT EXISTS idx_iindex_pub ON i_index (pub);' +
-      'COMMIT;')
-  }
-
-  async getMembers() {
-    // All those who has been subject to, or who are currently subject to kicking. Make one result per pubkey.
-    const pubkeys = await this.query('SELECT DISTINCT(pub) FROM ' + this.table);
-    // We get the full representation for each member
-    const reduced = await Promise.all(pubkeys.map(async (entry) => {
-      const reducable = await this.reducable(entry.pub);
-      return Indexer.DUP_HELPERS.reduce(reducable);
-    }));
-    // Filter on those to be kicked, return their pubkey
-    const filtered = _.filter(reduced, (entry:IindexEntry) => entry.member);
-    return filtered.map((t:IindexEntry) => this.toCorrectEntity(t))
-  }
-
-  getMembersPubkeys() {
-    return this.query('SELECT i1.pub ' +
-      'FROM i_index i1 ' +
-      'WHERE i1.member ' +
-      'AND CAST(i1.written_on as int) = (' +
-      ' SELECT MAX(CAST(i2.written_on as int)) ' +
-      ' FROM i_index i2 ' +
-      ' WHERE i1.pub = i2.pub ' +
-      ' AND i2.member IS NOT NULL' +
-      ')')
-  }
-
-  async getToBeKickedPubkeys() {
-    // All those who has been subject to, or who are currently subject to kicking. Make one result per pubkey.
-    const reducables = Indexer.DUP_HELPERS.reduceBy(await this.sqlFind({ kick: true }), ['pub']);
-    // We get the full representation for each member
-    const reduced = await Promise.all(reducables.map(async (entry) => {
-      const reducable = await this.reducable(entry.pub);
-      return Indexer.DUP_HELPERS.reduce(reducable);
-    }))
-    // Filter on those to be kicked, return their pubkey
-    return _.filter(reduced, (entry:IindexEntry) => entry.kick).map((entry:IindexEntry) => entry.pub);
-  }
-
-  async searchThoseMatching(search:string) {
-    const reducables = Indexer.DUP_HELPERS.reduceBy(await this.sqlFindLikeAny({
-        pub: "%" + search + "%",
-        uid: "%" + search + "%"
-      }), ['pub']);
-    // We get the full representation for each member
-    return await Promise.all(reducables.map(async (entry) => {
-      return this.toCorrectEntity(Indexer.DUP_HELPERS.reduce(await this.reducable(entry.pub)))
-    }))
-  }
-
-  getFromPubkey(pubkey:string) {
-    return this.entityOrNull('pub', pubkey) as Promise<FullIindexEntry|null>
-  }
-
-  getFromUID(uid:string, retrieveOnPubkey = false) {
-    return this.entityOrNull('uid', uid, retrieveOnPubkey)
-  }
-
-  getFullFromPubkey(pub:string): Promise<FullIindexEntry> {
-    return this.entityOrNull('pub', pub) as Promise<FullIindexEntry>
-  }
-
-  getFullFromUID(uid:string): Promise<FullIindexEntry|null> {
-    return this.entityOrNull('uid', uid, true) as Promise<FullIindexEntry|null>
-  }
-
-  getFullFromHash(hash:string): Promise<FullIindexEntry|null> {
-    return this.entityOrNull('hash', hash, true) as Promise<FullIindexEntry|null>
-  }
-
-  reducable(pub:string) {
-    return this.query('SELECT * FROM ' + this.table + ' WHERE pub = ? ORDER BY CAST(written_on as integer) ASC', [pub])
-  }
-
-  removeBlock(blockstamp:string) {
-    return this.exec('DELETE FROM ' + this.table + ' WHERE written_on = \'' + blockstamp + '\'')
-  }
-
-  private async entityOrNull(field:string, value:any, retrieveOnField:boolean = false) {
-    let reducable = await this.query('SELECT * FROM ' + this.table + ' WHERE ' + field + ' = ?', [value]);
-    if (reducable.length) {
-      if (retrieveOnField) {
-        // Force full retrieval on `pub` field
-        reducable = await this.query('SELECT * FROM ' + this.table + ' WHERE pub = ? ORDER BY CAST(written_on as int) ASC', [reducable[0].pub]);
-      }
-      return this.toCorrectEntity(Indexer.DUP_HELPERS.reduce(reducable));
-    }
-    return null;
-  }
-
-  private toCorrectEntity(row:IindexEntry): OldIindexEntry {
-    // Old field
-    return {
-      pubkey: row.pub,
-      pub: row.pub,
-      buid: row.created_on,
-      revocation_sig: null,
-      uid: row.uid,
-      hash: row.hash,
-      sig: row.sig,
-      created_on: row.created_on,
-      member: row.member,
-      wasMember: row.wasMember,
-      kick: row.kick,
-      wotb_id: row.wotb_id,
-      age: row.age,
-      index: row.index,
-      op: row.op,
-      writtenOn: row.writtenOn,
-      written_on: row.written_on
-    }
-  }
-
-  async getFromPubkeyOrUid(search: string) {
-    const idty = await this.getFromPubkey(search)
-    if (idty) {
-      return idty
-    }
-    return this.getFromUID(search, true) as Promise<FullIindexEntry|null>
-  }
-}
diff --git a/app/lib/dal/sqliteDAL/index/MIndexDAL.ts b/app/lib/dal/sqliteDAL/index/MIndexDAL.ts
deleted file mode 100644
index 29ab2c215e6c051fbdc1e8035aff7d064b42f148..0000000000000000000000000000000000000000
--- a/app/lib/dal/sqliteDAL/index/MIndexDAL.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
-// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU Affero General Public License for more details.
-
-import {SQLiteDriver} from "../../drivers/SQLiteDriver";
-import {AbstractIndex} from "../AbstractIndex";
-import {FullMindexEntry, Indexer, MindexEntry} from "../../../indexer";
-
-export class MIndexDAL extends AbstractIndex<MindexEntry> {
-
-  constructor(driver:SQLiteDriver) {
-    super(
-      driver,
-      'm_index',
-      // PK fields
-      ['op', 'pub', 'created_on', 'written_on'],
-      // Fields
-      [
-        'op',
-        'pub',
-        'created_on',
-        'written_on',
-        'writtenOn',
-        'expires_on',
-        'expired_on',
-        'revokes_on',
-        'revoked_on',
-        'chainable_on',
-        'leaving',
-        'revocation'
-      ],
-      // Arrays
-      [],
-      // Booleans
-      ['leaving'],
-      // BigIntegers
-      [],
-      // Transient
-      []
-    )
-  }
-
-  async init() {
-    await this.exec('BEGIN;' +
-      'CREATE TABLE IF NOT EXISTS ' + this.table + ' (' +
-      'op VARCHAR(10) NOT NULL,' +
-      'pub VARCHAR(50) NOT NULL,' +
-      'created_on VARCHAR(80) NOT NULL,' +
-      'written_on VARCHAR(80) NOT NULL,' +
-      'expires_on INTEGER NULL,' +
-      'expired_on INTEGER NULL,' +
-      'revokes_on INTEGER NULL,' +
-      'revoked_on INTEGER NULL,' +
-      'leaving BOOLEAN NULL,' +
-      'revocation VARCHAR(80) NULL,' +
-      'PRIMARY KEY (op,pub,created_on,written_on)' +
-      ');' +
-      'CREATE INDEX IF NOT EXISTS idx_mindex_pub ON m_index (pub);' +
-      'COMMIT;')
-  }
-
-  async getReducedMS(pub:string): Promise<FullMindexEntry|null> {
-    const reducables = await this.reducable(pub);
-    if (reducables.length) {
-      return Indexer.DUP_HELPERS.reduce(reducables) as FullMindexEntry
-    }
-    return null
-  }
-
-  reducable(pub:string) {
-    return this.query('SELECT * FROM ' + this.table + ' WHERE pub = ? ORDER BY CAST(written_on as integer) ASC', [pub])
-}
-
-  async removeBlock(blockstamp:string) {
-    return this.exec('DELETE FROM ' + this.table + ' WHERE written_on = \'' + blockstamp + '\'')
-  }
-
-  async getRevokedPubkeys() {
-    // All those who has been revoked. Make one result per pubkey.
-    const revovedMemberships = await this.sqlFind({ revoked_on: { $null: false} });
-
-    // Filter on those to be revoked, return their pubkey
-    return revovedMemberships.map((entry:MindexEntry) => entry.pub);
-  }
-}
diff --git a/app/lib/dal/sqliteDAL/index/SIndexDAL.ts b/app/lib/dal/sqliteDAL/index/SIndexDAL.ts
deleted file mode 100644
index 8161004f340ff0c561ce0c744e425be66e75e615..0000000000000000000000000000000000000000
--- a/app/lib/dal/sqliteDAL/index/SIndexDAL.ts
+++ /dev/null
@@ -1,143 +0,0 @@
-// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
-// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU Affero General Public License for more details.
-
-import {Indexer, SindexEntry} from "../../../indexer"
-import {SQLiteDriver} from "../../drivers/SQLiteDriver"
-import {AbstractIndex} from "../AbstractIndex"
-import {CommonConstants} from "../../../common-libs/constants"
-
-const _ = require('underscore');
-const constants = require('../../../constants');
-
-export class SIndexDAL extends AbstractIndex<SindexEntry> {
-
-  constructor(driver:SQLiteDriver) {
-    super(
-      driver,
-      's_index',
-      // PK fields
-      ['op', 'identifier', 'pos', 'written_on'],
-      // Fields
-      [
-        'op',
-        'tx',
-        'identifier',
-        'pos',
-        'created_on',
-        'written_on',
-        'writtenOn',
-        'written_time',
-        'amount',
-        'base',
-        'locktime',
-        'consumed',
-        'conditions'
-      ],
-      // Arrays
-      [],
-      // Booleans
-      ['consumed'],
-      // BigIntegers
-      [],
-      // Transient
-      []
-    )
-  }
-
-  async init() {
-    await this.exec('BEGIN;' +
-      'CREATE TABLE IF NOT EXISTS ' + this.table + ' (' +
-      'op VARCHAR(10) NOT NULL,' +
-      'tx VARCHAR(80) NULL,' +
-      'identifier VARCHAR(64) NOT NULL,' +
-      'pos INTEGER NOT NULL,' +
-      'created_on VARCHAR(80) NULL,' +
-      'written_on VARCHAR(80) NOT NULL,' +
-      'written_time INTEGER NOT NULL,' +
-      'amount INTEGER NULL,' +
-      'base INTEGER NULL,' +
-      'locktime INTEGER NULL,' +
-      'consumed BOOLEAN NOT NULL,' +
-      'conditions TEXT,' +
-      'PRIMARY KEY (op,identifier,pos,written_on)' +
-      ');' +
-      'CREATE INDEX IF NOT EXISTS idx_sindex_identifier ON s_index (identifier);' +
-      'CREATE INDEX IF NOT EXISTS idx_sindex_pos ON s_index (pos);' +
-      'COMMIT;')
-  }
-
-  async removeBlock(blockstamp:string) {
-    await this.exec('DELETE FROM ' + this.table + ' WHERE written_on = \'' + blockstamp + '\'')
-  }
-
-  async getSource(identifier:string, pos:number) {
-    const reducable = await this.query('SELECT * FROM ' + this.table + ' s1 ' +
-      'WHERE s1.identifier = ? ' +
-      'AND s1.pos = ? ' +
-      'ORDER BY op ASC', [identifier, pos]);
-    if (reducable.length == 0) {
-      return null;
-    } else {
-      const src = Indexer.DUP_HELPERS.reduce(reducable);
-      src.type = src.tx ? 'T' : 'D';
-      return src;
-    }
-  }
-
-  async getUDSources(pubkey:string) {
-    const reducables = await this.query('SELECT * FROM ' + this.table + ' s1 ' +
-      'WHERE conditions = ? ' +
-      'AND s1.tx IS NULL ' +
-      'ORDER BY op ASC', ['SIG(' + pubkey + ')']);
-    const reduced = Indexer.DUP_HELPERS.reduceBy(reducables, ['identifier', 'pos']).map((src) => {
-      src.type = src.tx ? 'T' : 'D';
-      return src;
-    });
-    return _.sortBy(reduced, (row:SindexEntry) => row.type == 'D' ? 0 : 1);
-  }
-
-  getAvailableForPubkey(pubkey:string) {
-    return this.getAvailableForConditions('%SIG(' + pubkey + ')%')
-  }
-
-  async getAvailableForConditions(conditionsStr:string): Promise<{ amount:number, base:number }[]> {
-    const potentials = await this.query('SELECT * FROM ' + this.table + ' s1 ' +
-      'WHERE s1.op = ? ' +
-      'AND conditions LIKE ? ' +
-      'AND NOT EXISTS (' +
-      ' SELECT * ' +
-      ' FROM s_index s2 ' +
-      ' WHERE s2.identifier = s1.identifier ' +
-      ' AND s2.pos = s1.pos ' +
-      ' AND s2.op = ?' +
-      ') ' +
-      'ORDER BY CAST(SUBSTR(written_on, 0, INSTR(written_on, "-")) as number)', [CommonConstants.IDX_CREATE, conditionsStr, CommonConstants.IDX_UPDATE]);
-    const sources = potentials.map((src) => {
-      src.type = src.tx ? 'T' : 'D';
-      return src;
-    });
-    return _.sortBy(sources, (row:SindexEntry) => row.type == 'D' ? 0 : 1);
-  }
-
-  async trimConsumedSource(belowNumber:number) {
-    const toDelete = await this.query('SELECT * FROM ' + this.table + ' WHERE consumed AND CAST(written_on as int) < ?', [belowNumber]);
-    const queries = [];
-    for (const row of toDelete) {
-      const sql = "DELETE FROM " + this.table + " " +
-        "WHERE identifier like '" + row.identifier + "' " +
-        "AND pos = " + row.pos;
-      queries.push(sql);
-    }
-    await this.exec(queries.join(';\n'));
-  }
-}
diff --git a/app/lib/db/OldIindexEntry.ts b/app/lib/db/OldIindexEntry.ts
new file mode 100644
index 0000000000000000000000000000000000000000..308969f906b983034a717c6503d54ac9ca1eee61
--- /dev/null
+++ b/app/lib/db/OldIindexEntry.ts
@@ -0,0 +1,7 @@
+import {IindexEntry} from "../indexer"
+
+export interface OldIindexEntry extends IindexEntry {
+  pubkey: string
+  buid: string | null
+  revocation_sig:string | null
+}
diff --git a/app/lib/indexer.ts b/app/lib/indexer.ts
index 9f4e720f6527903afb6c15c44208fe0f43b95f0e..705e632dc366f9689351786d94b4dce913f265dd 100644
--- a/app/lib/indexer.ts
+++ b/app/lib/indexer.ts
@@ -27,8 +27,7 @@ import {FileDAL} from "./dal/fileDAL"
 import {DBBlock} from "./db/DBBlock"
 import {DBWallet} from "./db/DBWallet"
 import {Tristamp} from "./common/Tristamp"
-
-const _               = require('underscore');
+import {Underscore} from "./common-libs/underscore"
 
 const constants       = CommonConstants
 
@@ -181,18 +180,18 @@ export interface FullSindexEntry {
 }
 
 export interface Ranger {
-  (n:number, m:number, prop?:string): Promise<DBHead[]>
+  (n:number, m:number): Promise<DBHead[]>
 }
 
-function pushIindex(index: any[], entry: IindexEntry): void {
+function pushIindex(index: IndexEntry[], entry: IindexEntry): void {
   index.push(entry)
 }
 
-function pushMindex(index: any[], entry: MindexEntry): void {
+function pushMindex(index: IndexEntry[], entry: MindexEntry): void {
   index.push(entry)
 }
 
-function pushCindex(index: any[], entry: CindexEntry): void {
+function pushCindex(index: IndexEntry[], entry: CindexEntry): void {
   index.push(entry)
 }
 
@@ -200,7 +199,7 @@ export interface AccountsGarbagingDAL {
   getWallet: (conditions: string) => Promise<DBWallet>
   saveWallet: (wallet: DBWallet) => Promise<void>
   sindexDAL: {
-    getAvailableForConditions: (conditions: string) => any
+    getAvailableForConditions: (conditions: string) => Promise<SindexEntry[]>
   }
 }
 
@@ -261,7 +260,7 @@ export class Indexer {
     // Joiners (newcomer or join back)
     for (const inlineMS of block.joiners) {
       const ms = MembershipDTO.fromInline(inlineMS);
-      const matchesANewcomer = _.filter(index, (row: IindexEntry) => row.index == constants.I_INDEX && row.pub == ms.issuer).length > 0;
+      const matchesANewcomer = Underscore.filter(index, (row: IindexEntry) => row.index == constants.I_INDEX && row.pub == ms.issuer).length > 0;
       if (matchesANewcomer) {
         // Newcomer
         pushMindex(index, {
@@ -495,25 +494,20 @@ export class Indexer {
 
   static async quickCompleteGlobalScope(block: BlockDTO, conf: CurrencyConfDTO, bindex: DBHead[], iindex: IindexEntry[], mindex: MindexEntry[], cindex: CindexEntry[], dal:FileDAL) {
 
-    function range(start: number, end: number, property = ""): any {
-      let theRange;
+    async function range(start: number, end: number) {
+      let theRange:DBHead[] = []
       end = Math.min(end, bindex.length);
       if (start == 1) {
         theRange = bindex.slice(-end);
       } else {
         theRange = bindex.slice(-end, -start + 1);
       }
-      theRange.reverse();
-      if (property) {
-        // Filter on a particular property
-        return theRange.map((b:any) => b[property]);
-      } else {
-        return theRange;
-      }
+      theRange.reverse()
+      return theRange
     }
 
     async function head(n:number) {
-      return range(n, n)[0];
+      return (await range(n, n))[0]
     }
 
     const HEAD = new DBHead()
@@ -637,7 +631,7 @@ export class Indexer {
     if (HEAD.number > 0) {
       HEAD.issuerIsMember = reduce(await dal.iindexDAL.reducable(HEAD.issuer)).member;
     } else {
-      HEAD.issuerIsMember = reduce(_.where(iindex, { pub: HEAD.issuer })).member;
+      HEAD.issuerIsMember = reduce(Underscore.where(iindex, { pub: HEAD.issuer })).member;
     }
 
     // BR_G04
@@ -664,11 +658,11 @@ export class Indexer {
 
     // BR_G10
     if (HEAD.number == 0) {
-      HEAD.membersCount = count(_.filter(iindex, (entry:IindexEntry) => entry.member === true));
+      HEAD.membersCount = count(Underscore.filter(iindex, (entry:IindexEntry) => entry.member === true));
     } else {
       HEAD.membersCount = HEAD_1.membersCount
-        + count(_.filter(iindex, (entry:IindexEntry) => entry.member === true))
-        - count(_.filter(iindex, (entry:IindexEntry) => entry.member === false));
+        + count(Underscore.filter(iindex, (entry:IindexEntry) => entry.member === true))
+        - count(Underscore.filter(iindex, (entry:IindexEntry) => entry.member === false));
     }
 
     // BR_G11
@@ -774,7 +768,7 @@ export class Indexer {
     // BR_G36
     await Promise.all(iindex.map(async (ENTRY: IindexEntry) => {
       const isMarkedAsToKick = reduce(await dal.iindexDAL.reducable(ENTRY.pub)).kick;
-      const isBeingRevoked = count(_.filter(mindex, (m:MindexEntry) => m.isBeingRevoked && m.pub == ENTRY.pub)) == 1;
+      const isBeingRevoked = count(Underscore.filter(mindex, m => !!(m.isBeingRevoked && m.pub == ENTRY.pub))) == 1
       ENTRY.hasToBeExcluded = isMarkedAsToKick || isBeingRevoked;
     }))
 
@@ -798,14 +792,14 @@ export class Indexer {
     // BR_G24
     // Global testing, because of wotb
     const oneIsOutdistanced = await checkPeopleAreNotOudistanced(
-      _.filter(mindex, (entry: MindexEntry) => !entry.revoked_on).map((entry: MindexEntry) => entry.pub),
-      cindex.reduce((newLinks:any, c: CindexEntry) => {
+      Underscore.filter(mindex, (entry: MindexEntry) => !entry.revoked_on).map((entry: MindexEntry) => entry.pub),
+      cindex.reduce((newLinks, c: CindexEntry) => {
         newLinks[c.receiver] = newLinks[c.receiver] || [];
         newLinks[c.receiver].push(c.issuer);
         return newLinks;
-      }, {}),
+      }, <{ [k:string]: string[] }>{}),
       // Newcomers
-      _.where(iindex, { op: constants.IDX_CREATE }).map((entry: IindexEntry) => entry.pub),
+      Underscore.where(iindex, { op: constants.IDX_CREATE }).map((entry: IindexEntry) => entry.pub),
       conf,
       dal
     );
@@ -823,7 +817,7 @@ export class Indexer {
     }))
 
     // BR_G26
-    await Promise.all(_.filter(mindex, (entry: MindexEntry) => entry.op == constants.IDX_UPDATE && entry.expired_on === 0).map(async (ENTRY: MindexEntry) => {
+    await Promise.all(Underscore.filter(mindex, (entry: MindexEntry) => entry.op == constants.IDX_UPDATE && entry.expired_on === 0).map(async (ENTRY: MindexEntry) => {
       ENTRY.joinsTwice = reduce(await dal.iindexDAL.reducable(ENTRY.pub)).member == true;
     }))
 
@@ -831,7 +825,7 @@ export class Indexer {
     await Promise.all(mindex.map(async (ENTRY: MindexEntry) => {
       if (ENTRY.type == 'JOIN' || ENTRY.type == 'ACTIVE') {
         const existing = count(await dal.cindexDAL.findByReceiverAndExpiredOn(ENTRY.pub, 0))
-        const pending = count(_.filter(cindex, (c:CindexEntry) => c.receiver == ENTRY.pub && c.expired_on == 0))
+        const pending = count(Underscore.filter(cindex, (c:CindexEntry) => c.receiver == ENTRY.pub && c.expired_on == 0))
         ENTRY.enoughCerts = (existing + pending) >= conf.sigQty;
       } else {
         ENTRY.enoughCerts = true;
@@ -871,7 +865,7 @@ export class Indexer {
       if (!ENTRY.revoked_on) {
         ENTRY.alreadyRevoked = false;
       } else {
-        ENTRY.alreadyRevoked = reduce(await dal.mindexDAL.reducable(ENTRY.pub)).revoked_on
+        ENTRY.alreadyRevoked = !!(reduce(await dal.mindexDAL.reducable(ENTRY.pub)).revoked_on)
       }
     }))
 
@@ -912,12 +906,12 @@ export class Indexer {
 
     // BR_G42
     await Promise.all(cindex.map(async (ENTRY: CindexEntry) => {
-      ENTRY.toNewcomer = count(_.where(iindex, { member: true, pub: ENTRY.receiver })) > 0;
+      ENTRY.toNewcomer = count(Underscore.where(iindex, { member: true, pub: ENTRY.receiver })) > 0;
     }))
 
     // BR_G43
     await Promise.all(cindex.map(async (ENTRY: CindexEntry) => {
-      ENTRY.toLeaver = reduce(await dal.mindexDAL.reducable(ENTRY.receiver)).leaving
+      ENTRY.toLeaver = !!(reduce(await dal.mindexDAL.reducable(ENTRY.receiver)).leaving)
     }))
 
     // BR_G44
@@ -947,7 +941,7 @@ export class Indexer {
     }))
 
     // BR_G102
-    await Promise.all(_.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY: SindexEntry) => {
+    await Promise.all(Underscore.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY: SindexEntry) => {
       if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') {
         ENTRY.age = 0;
       } else {
@@ -961,10 +955,10 @@ export class Indexer {
     }))
 
     const getInputLocalFirstOrFallbackGlobally = async (sindex:SindexEntry[], ENTRY:SindexEntry) => {
-      let source = _.filter(sindex, (src:SindexEntry) =>
+      let source = Underscore.filter(sindex, src =>
         src.identifier == ENTRY.identifier
         && src.pos == ENTRY.pos
-        && src.conditions
+        && src.conditions !== ''
         && src.op === constants.IDX_CREATE)[0];
       if (!source) {
         const reducable = await dal.sindexDAL.findByIdentifierPosAmountBase(
@@ -979,21 +973,21 @@ export class Indexer {
     }
 
     // BR_G46
-    await Promise.all(_.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY: SindexEntry) => {
+    await Promise.all(Underscore.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY: SindexEntry) => {
       const source = await getInputLocalFirstOrFallbackGlobally(sindex, ENTRY)
       ENTRY.conditions = source.conditions; // We valuate the input conditions, so we can map these records to a same account
       ENTRY.available = source.consumed === false;
     }))
 
     // BR_G47
-    await Promise.all(_.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY: SindexEntry) => {
+    await Promise.all(Underscore.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY: SindexEntry) => {
       const source = await getInputLocalFirstOrFallbackGlobally(sindex, ENTRY)
       ENTRY.conditions = source.conditions;
       ENTRY.isLocked = !txSourceUnlock(ENTRY, source, HEAD);
     }))
 
     // BR_G48
-    await Promise.all(_.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY: SindexEntry) => {
+    await Promise.all(Underscore.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY: SindexEntry) => {
       const source = await getInputLocalFirstOrFallbackGlobally(sindex, ENTRY)
       ENTRY.isTimeLocked = ENTRY.written_time - source.written_time < ENTRY.locktime;
     }))
@@ -1015,7 +1009,7 @@ export class Indexer {
     if (HEAD.number == 0) {
       HEAD.issuersCount = 0;
     } else {
-      HEAD.issuersCount = count(uniq(await range(1, HEAD_1.issuersFrame, 'issuer'))); // TODO
+      HEAD.issuersCount = count(uniq(Underscore.pluck(await range(1, HEAD_1.issuersFrame), 'issuer')))
     }
   }
 
@@ -1049,8 +1043,8 @@ export class Indexer {
   }
 
   // BR_G07
-  static async prepareAvgBlockSize(HEAD: DBHead, range: (n:number,m:number,s:string)=>Promise<number[]>) {
-    HEAD.avgBlockSize = average(await range(1, HEAD.issuersCount, 'bsize'))
+  static async prepareAvgBlockSize(HEAD: DBHead, range:Ranger) {
+    HEAD.avgBlockSize = average(Underscore.pluck(await range(1, HEAD.issuersCount), 'bsize'))
   }
 
   // BR_G09
@@ -1161,11 +1155,11 @@ export class Indexer {
       medianOfBlocksInFrame = 1;
     } else {
       const ranged = await range(1, HEAD_1.issuersFrame)
-      const blocksInFrame = _.filter(ranged, (b:DBHead) => b.number <= HEAD_1.number);
-      const issuersInFrame = blocksInFrame.map((b:BlockDTO) => b.issuer);
-      blocksOfIssuer = _.filter(blocksInFrame, (entry:BlockDTO) => entry.issuer == HEAD.issuer);
+      const blocksInFrame = Underscore.filter(ranged, (b:DBHead) => b.number <= HEAD_1.number)
+      const issuersInFrame = blocksInFrame.map(b => b.issuer)
+      blocksOfIssuer = Underscore.filter(blocksInFrame, entry => entry.issuer == HEAD.issuer)
       nbPersonalBlocksInFrame = count(blocksOfIssuer);
-      const blocksPerIssuerInFrame = uniq(issuersInFrame).map((issuer:string) => count(_.where(blocksInFrame, { issuer })));
+      const blocksPerIssuerInFrame = uniq(issuersInFrame).map((issuer:string) => count(Underscore.where(blocksInFrame, { issuer })));
       medianOfBlocksInFrame = Math.max(1, median(blocksPerIssuerInFrame));
       if (nbPersonalBlocksInFrame == 0) {
         nbPreviousIssuers = 0;
@@ -1191,7 +1185,7 @@ export class Indexer {
 
   // BR_G19
   static async prepareIdentitiesAge(iindex: IindexEntry[], HEAD: DBHead, HEAD_1: DBHead, conf: CurrencyConfDTO, dal:FileDAL) {
-    await Promise.all(_.where(iindex, { op: constants.IDX_CREATE }).map(async (ENTRY: IindexEntry) => {
+    await Promise.all(Underscore.where(iindex, { op: constants.IDX_CREATE }).map(async (ENTRY: IindexEntry) => {
       if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') {
         ENTRY.age = 0;
       } else {
@@ -1207,7 +1201,7 @@ export class Indexer {
 
   // BR_G22
   static async prepareMembershipsAge(mindex: MindexEntry[], HEAD: DBHead, HEAD_1: DBHead, conf: CurrencyConfDTO, dal:FileDAL) {
-    await Promise.all(_.filter(mindex, (entry: MindexEntry) => !entry.revoked_on).map(async (ENTRY:MindexEntry) => {
+    await Promise.all(Underscore.filter(mindex, (entry: MindexEntry) => !entry.revoked_on).map(async (ENTRY:MindexEntry) => {
       if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') {
         ENTRY.age = 0;
       } else {
@@ -1562,11 +1556,11 @@ export class Indexer {
   static async ruleToBeKickedArePresent(iindex: IindexEntry[], dal:FileDAL) {
     const toBeKicked = await dal.iindexDAL.getToBeKickedPubkeys();
     for (const toKick of toBeKicked) {
-      if (count(_.where(iindex, { pub: toKick, isBeingKicked: true })) !== 1) {
+      if (count(Underscore.where(iindex, { pub: toKick, isBeingKicked: true })) !== 1) {
         return false;
       }
     }
-    const beingKicked = _.filter(iindex, (i:IindexEntry) => i.member === false);
+    const beingKicked = Underscore.filter(iindex, (i:IindexEntry) => i.member === false);
     for (const entry of beingKicked) {
       if (!entry.hasToBeExcluded) {
         return false;
@@ -1585,7 +1579,7 @@ export class Indexer {
 
   // BR_G87
   static ruleInputIsAvailable(sindex: SindexEntry[]) {
-    const inputs = _.where(sindex, { op: constants.IDX_UPDATE });
+    const inputs = Underscore.where(sindex, { op: constants.IDX_UPDATE });
     for (const ENTRY of inputs) {
       if (!ENTRY.available) {
         return false;
@@ -1596,7 +1590,7 @@ export class Indexer {
 
   // BR_G88
   static ruleInputIsUnlocked(sindex: SindexEntry[]) {
-    const inputs = _.where(sindex, { op: constants.IDX_UPDATE });
+    const inputs = Underscore.where(sindex, { op: constants.IDX_UPDATE });
     for (const ENTRY of inputs) {
       if (ENTRY.isLocked) {
         return false;
@@ -1607,7 +1601,7 @@ export class Indexer {
 
   // BR_G89
   static ruleInputIsTimeUnlocked(sindex: SindexEntry[]) {
-    const inputs = _.where(sindex, { op: constants.IDX_UPDATE });
+    const inputs = Underscore.where(sindex, { op: constants.IDX_UPDATE });
     for (const ENTRY of inputs) {
       if (ENTRY.isTimeLocked) {
         return false;
@@ -1618,9 +1612,9 @@ export class Indexer {
 
   // BR_G90
   static ruleOutputBase(sindex: SindexEntry[], HEAD_1: DBHead) {
-    const inputs = _.where(sindex, { op: constants.IDX_CREATE });
+    const inputs = Underscore.where(sindex, { op: constants.IDX_CREATE });
     for (const ENTRY of inputs) {
-      if (ENTRY.unitBase > HEAD_1.unitBase) {
+      if (ENTRY.base > HEAD_1.unitBase) {
         return false;
       }
     }
@@ -1658,12 +1652,12 @@ export class Indexer {
       acc[src.conditions] = true;
       return acc;
     }, {}));
-    const wallets: { [k:string]: Promise<any> } = accounts.reduce((map: { [k:string]: Promise<any> }, acc) => {
+    const wallets: { [k:string]: Promise<DBWallet> } = accounts.reduce((map: { [k:string]: Promise<DBWallet> }, acc) => {
       map[acc] = dal.getWallet(acc);
       return map;
     }, {});
     for (const account of accounts) {
-      const localAccountEntries = _.filter(sindex, (src:SindexEntry) => src.conditions == account);
+      const localAccountEntries = Underscore.filter(sindex, (src:SindexEntry) => src.conditions == account);
       const wallet = await wallets[account];
       const balance = wallet.balance
       const variations = localAccountEntries.reduce((sum:number, src:SindexEntry) => {
@@ -1677,7 +1671,7 @@ export class Indexer {
       if (balance + variations < constants.ACCOUNT_MINIMUM_CURRENT_BASED_AMOUNT * Math.pow(10, HEAD.unitBase)) {
         const globalAccountEntries = await dal.sindexDAL.getAvailableForConditions(account)
         for (const src of localAccountEntries.concat(globalAccountEntries)) {
-          const sourceBeingConsumed = _.filter(sindex, (entry:SindexEntry) => entry.op === 'UPDATE' && entry.identifier == src.identifier && entry.pos == src.pos).length > 0;
+          const sourceBeingConsumed = Underscore.filter(sindex, (entry:SindexEntry) => entry.op === 'UPDATE' && entry.identifier == src.identifier && entry.pos == src.pos).length > 0;
           if (!sourceBeingConsumed) {
             garbages.push({
               op: 'UPDATE',
@@ -1742,7 +1736,7 @@ export class Indexer {
   // BR_G94
   static async ruleIndexGenExclusionByMembership(HEAD: DBHead, mindex: MindexEntry[], dal:FileDAL) {
     const exclusions = [];
-    const memberships = _.filter(mindex, (entry: MindexEntry) => entry.expired_on);
+    const memberships = Underscore.filter(mindex, entry => !!entry.expired_on)
     for (const MS of memberships) {
       const idty = await dal.iindexDAL.getFullFromPubkey(MS.pub);
       if (idty.member) {
@@ -1761,13 +1755,13 @@ export class Indexer {
   // BR_G95
   static async ruleIndexGenExclusionByCertificatons(HEAD: DBHead, cindex: CindexEntry[], iindex: IindexEntry[], conf: ConfDTO, dal:FileDAL) {
     const exclusions = [];
-    const expiredCerts = _.filter(cindex, (c: CindexEntry) => c.expired_on > 0);
+    const expiredCerts = Underscore.filter(cindex, (c: CindexEntry) => c.expired_on > 0);
     for (const CERT of expiredCerts) {
-      const just_expired = _.filter(cindex, (c: CindexEntry) => c.receiver == CERT.receiver && c.expired_on > 0);
-      const just_received = _.filter(cindex, (c: CindexEntry) => c.receiver == CERT.receiver && c.expired_on == 0);
+      const just_expired = Underscore.filter(cindex, (c: CindexEntry) => c.receiver == CERT.receiver && c.expired_on > 0);
+      const just_received = Underscore.filter(cindex, (c: CindexEntry) => c.receiver == CERT.receiver && c.expired_on == 0);
       const non_expired_global = await dal.cindexDAL.getValidLinksTo(CERT.receiver);
       if ((count(non_expired_global) - count(just_expired) + count(just_received)) < conf.sigQty) {
-        const isInExcluded = _.filter(iindex, (i: IindexEntry) => i.member === false && i.pub === CERT.receiver)[0];
+        const isInExcluded = Underscore.filter(iindex, (i: IindexEntry) => i.member === false && i.pub === CERT.receiver)[0];
         const idty = await dal.iindexDAL.getFullFromPubkey(CERT.receiver)
         if (!isInExcluded && idty.member) {
           exclusions.push({
@@ -1865,19 +1859,18 @@ export class Indexer {
   static DUP_HELPERS = {
 
     reduce,
-    reduceTyped,
     reduceBy: reduceBy,
     getMaxBlockSize: (HEAD: DBHead) => Math.max(500, Math.ceil(1.1 * HEAD.avgBlockSize)),
     checkPeopleAreNotOudistanced
   }
 }
 
-function count(range:any[]) {
+function count<T>(range:T[]) {
   return range.length;
 }
 
-function uniq(range:any[]) {
-  return _.uniq(range);
+function uniq(range:string[]) {
+  return Underscore.uniq(range)
 }
 
 function average(values:number[]) {
@@ -1913,58 +1906,43 @@ function blockstamp(aNumber: number, aHash: string) {
   return [aNumber, aHash].join('-');
 }
 
-function reduce(records: any[]) {
-  return records.reduce((obj:any, record) => {
-    const keys = Object.keys(record);
+function reduce<T>(records: T[]): T {
+  return records.reduce((obj:T, record) => {
+    const keys = Underscore.keys(record)
     for (const k of keys) {
       if (record[k] !== undefined && record[k] !== null) {
         obj[k] = record[k];
       }
     }
-    return obj;
-  }, {});
-}
-
-function reduceTyped<T>(records: T[]): T {
-  const map:any = {}
-  return records.reduce((obj, record:any) => {
-    // Overwrite properties of the object `obj`
-    const keys = Object.keys(record);
-    for (const k of keys) {
-      if (record[k] !== undefined && record[k] !== null) {
-        obj[k] = record[k]
-      }
-    }
     return obj
-  }, map)
+  }, <T>{})
 }
 
-function reduceBy(reducables: IndexEntry[], properties: string[]): any[] {
-  const reduced = reducables.reduce((map: any, entry: any) => {
-    const id = properties.map((prop) => entry[prop]).join('-');
-    map[id] = map[id] || [];
-    map[id].push(entry);
-    return map;
-  }, {});
-  return _.values(reduced).map((value: SindexEntry[]) => Indexer.DUP_HELPERS.reduce(value));
+function reduceBy<T extends IndexEntry>(reducables: T[], properties: (keyof T)[]): T[] {
+  const reduced: { [k:string]: T[] } = reducables.reduce((map, entry) => {
+    const id = properties.map((prop) => entry[prop]).join('-')
+    map[id] = map[id] || []
+    map[id].push(entry)
+    return map
+  }, <{ [k:string]: T[] }>{})
+  return Underscore.values(reduced).map(value => Indexer.DUP_HELPERS.reduce(value))
 }
 
-async function checkPeopleAreNotOudistanced (pubkeys: string[], newLinks: any, newcomers: string[], conf: ConfDTO, dal:FileDAL) {
+async function checkPeopleAreNotOudistanced (pubkeys: string[], newLinks: { [k:string]: string[] }, newcomers: string[], conf: ConfDTO, dal:FileDAL) {
   // let wotb = dal.wotb;
   let wotb = dal.wotb.memCopy();
   let current = await dal.getCurrentBlockOrNull();
   let membersCount = current ? current.membersCount : 0;
-  // TODO: make a temporary copy of the WoT in RAM
   // We add temporarily the newcomers to the WoT, to integrate their new links
-  let nodesCache = newcomers.reduce((map: any, pubkey) => {
+  let nodesCache = newcomers.reduce((map, pubkey) => {
     let nodeID = wotb.addNode();
     map[pubkey] = nodeID;
     wotb.setEnabled(false, nodeID); // These are not members yet
     return map;
-  }, {});
+  }, <{ [k:string]: number }>{});
   // Add temporarily the links to the WoT
   let tempLinks = [];
-  let toKeys = _.keys(newLinks);
+  let toKeys = Underscore.keys(newLinks)
   for (const toKey of toKeys) {
     let toNode = await getNodeIDfromPubkey(nodesCache, toKey, dal);
     for (const fromKey of newLinks[toKey]) {
@@ -1992,13 +1970,13 @@ async function checkPeopleAreNotOudistanced (pubkeys: string[], newLinks: any, n
   return error ? true : false;
 }
 
-async function getNodeIDfromPubkey(nodesCache: any, pubkey: string, dal:FileDAL) {
+async function getNodeIDfromPubkey(nodesCache: { [k:string]: number }, pubkey: string, dal:FileDAL) {
   let toNode = nodesCache[pubkey];
   // Eventually cache the target nodeID
   if (toNode === null || toNode === undefined) {
     let idty = await dal.getWrittenIdtyByPubkeyForWotbID(pubkey)
-    toNode = idty.wotb_id;
-    nodesCache[pubkey] = toNode;
+    toNode = idty.wotb_id
+    nodesCache[pubkey] = toNode
   }
   return toNode;
 }