From 8840d45cab7d052a8dd69f26edb5f44e1068e80a Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Wed, 18 Jan 2017 11:33:28 +0100
Subject: [PATCH] [enh] #739 BMA is now an external module

---
 app/cli.js                                    |    7 -
 app/controllers/abstract.js                   |   22 -
 app/controllers/blockchain.js                 |  148 --
 app/controllers/network.js                    |   71 -
 app/controllers/node.js                       |   38 -
 app/controllers/transactions.js               |  110 -
 app/controllers/uds.js                        |   63 -
 app/controllers/wot.js                        |  242 ---
 app/lib/constants.js                          |   32 -
 app/lib/contacter.js                          |    4 +-
 app/lib/entity/configuration.js               |    7 -
 app/lib/helpers/http2raw.js                   |   38 -
 app/lib/helpers/http400.js                    |    9 -
 app/lib/helpers/parameters.js                 |  101 -
 app/lib/streams/bma.js                        |   31 -
 app/lib/streams/dtos.js                       |  449 ----
 app/lib/streams/jsoner.js                     |   21 -
 app/lib/streams/routes.js                     |  125 --
 app/lib/streams/sanitize.js                   |  118 --
 app/lib/system/limiter.js                     |  114 --
 app/lib/system/network.js                     |  255 +--
 app/lib/system/upnp.js                        |   66 -
 app/modules/bmapi.js                          |  564 -----
 doc/HTTP_API.md                               | 1812 -----------------
 index.js                                      |   16 +-
 package.json                                  |   13 +-
 server.js                                     |   22 +-
 test/dal/triming.js                           |    2 -
 test/fast/ddos-test.js                        |   39 -
 test/fast/limiter-test.js                     |   60 -
 test/integration/branches.js                  |    2 +-
 test/integration/branches2.js                 |    2 +-
 test/integration/branches_pending_data.js     |    2 +-
 test/integration/branches_revert.js           |    2 +-
 test/integration/branches_revert2.js          |    2 +-
 .../branches_revert_memberships.js            |    5 +-
 test/integration/branches_switch.js           |    2 +-
 .../integration/certification_chainability.js |    2 +-
 test/integration/collapse.js                  |    2 +-
 test/integration/crosschain-test.js           |    2 +-
 test/integration/forwarding.js                |    5 +-
 test/integration/http_api.js                  |    2 +-
 test/integration/identity-absorption.js       |    2 +-
 test/integration/identity-clean-test.js       |    2 +-
 test/integration/identity-expiry.js           |    2 +-
 test/integration/identity-kicking.js          |    2 +-
 test/integration/identity-same-pubkey.js      |    2 +-
 test/integration/identity-test.js             |    5 +-
 test/integration/lookup.js                    |    2 +-
 test/integration/network.js                   |    1 +
 test/integration/peer-outdated.js             |    2 +-
 test/integration/peerings.js                  |    2 +-
 test/integration/peers-same-pubkey.js         |    2 +-
 test/integration/revocation-test.js           |    5 +-
 test/integration/server-import-export.js      |    2 +-
 test/integration/server-sandbox.js            |    5 +-
 test/integration/start_generate_blocks.js     |    2 +-
 test/integration/tests.js                     |    5 +-
 test/integration/tools/node.js                |    9 +-
 test/integration/tools/toolbox.js             |    9 +-
 test/integration/transactions-chaining.js     |    5 +-
 test/integration/transactions-test.js         |    4 +-
 test/integration/v0.4-dividend.js             |    2 +-
 test/integration/v0.4-times.js                |    2 +-
 test/integration/v0.5-identity-blockstamp.js  |    4 +-
 test/integration/v0.5-transactions.js         |    4 +-
 test/integration/v0.6-difficulties.js         |    4 +-
 test/integration/v1.0-source-garbaging.js     |    4 +-
 test/integration/wotb.js                      |    2 +-
 69 files changed, 66 insertions(+), 4655 deletions(-)
 delete mode 100644 app/controllers/abstract.js
 delete mode 100644 app/controllers/blockchain.js
 delete mode 100644 app/controllers/network.js
 delete mode 100644 app/controllers/node.js
 delete mode 100644 app/controllers/transactions.js
 delete mode 100644 app/controllers/uds.js
 delete mode 100644 app/controllers/wot.js
 delete mode 100644 app/lib/helpers/http2raw.js
 delete mode 100644 app/lib/helpers/http400.js
 delete mode 100644 app/lib/helpers/parameters.js
 delete mode 100644 app/lib/streams/bma.js
 delete mode 100644 app/lib/streams/dtos.js
 delete mode 100644 app/lib/streams/jsoner.js
 delete mode 100644 app/lib/streams/routes.js
 delete mode 100644 app/lib/streams/sanitize.js
 delete mode 100644 app/lib/system/limiter.js
 delete mode 100644 app/lib/system/upnp.js
 delete mode 100644 app/modules/bmapi.js
 delete mode 100644 doc/HTTP_API.md
 delete mode 100644 test/fast/ddos-test.js
 delete mode 100644 test/fast/limiter-test.js

diff --git a/app/cli.js b/app/cli.js
index a4f04d0f7..16702d1fe 100644
--- a/app/cli.js
+++ b/app/cli.js
@@ -41,13 +41,6 @@ module.exports = () => {
         .option('-d, --mdb <name>', 'Database name (defaults to "duniter_default").')
 
         .option('--autoconf', 'With `config` and `init` commands, will guess the best network and key options witout asking for confirmation')
-        .option('--ipv4 <address>', 'IPv4 interface to listen for requests')
-        .option('--ipv6 <address>', 'IPv6 interface to listen for requests')
-        .option('--remoteh <host>', 'Remote interface others may use to contact this node')
-        .option('--remote4 <host>', 'Remote interface for IPv4 access')
-        .option('--remote6 <host>', 'Remote interface for IPv6 access')
-        .option('-p, --port <port>', 'Port to listen for requests', parseInt)
-        .option('--remotep <port>', 'Remote port others may use to contact this node')
         .option('--addep <endpoint>', 'With `config` command, add given endpoint to the list of endpoints of this node')
         .option('--remep <endpoint>', 'With `config` command, remove given endpoint to the list of endpoints of this node')
 
diff --git a/app/controllers/abstract.js b/app/controllers/abstract.js
deleted file mode 100644
index 977232e29..000000000
--- a/app/controllers/abstract.js
+++ /dev/null
@@ -1,22 +0,0 @@
-
-"use strict";
-const co = require('co');
-const dos2unix = require('../lib/system/dos2unix');
-
-module.exports = function AbstractController (server) {
-
-  const logger = require('../lib/logger')('abstractController');
-
-  this.pushEntity = (req, rawer, type) => co(function *() {
-    let rawDocument = rawer(req);
-    rawDocument = dos2unix(rawDocument);
-    const written = yield server.writeRaw(rawDocument, type);
-    try {
-      return written.json();
-    } catch (e) {
-      logger.error('Written:', written);
-      logger.error(e);
-      throw e;
-    }
-  });
-};
diff --git a/app/controllers/blockchain.js b/app/controllers/blockchain.js
deleted file mode 100644
index b920b8c5c..000000000
--- a/app/controllers/blockchain.js
+++ /dev/null
@@ -1,148 +0,0 @@
-"use strict";
-
-const co               = require('co');
-const _                = require('underscore');
-const constants        = require('../lib/constants');
-const http2raw         = require('../lib/helpers/http2raw');
-const Membership       = require('../lib/entity/membership');
-const AbstractController = require('./abstract');
-
-module.exports = function (server) {
-  return new BlockchainBinding(server);
-};
-
-function BlockchainBinding (server) {
-
-  AbstractController.call(this, server);
-
-  const conf = server.conf;
-
-  // Services
-  const ParametersService = server.ParametersService;
-  const BlockchainService = server.BlockchainService;
-  const IdentityService   = server.IdentityService;
-
-  // Models
-  const Block      = require('../lib/entity/block');
-  const Stat       = require('../lib/entity/stat');
-
-  this.parseMembership = (req) => this.pushEntity(req, http2raw.membership, constants.ENTITY_MEMBERSHIP);
-
-  this.parseBlock = (req) => this.pushEntity(req, http2raw.block, constants.ENTITY_BLOCK);
-
-  this.parameters = () => server.dal.getParameters();
-
-  this.with = {
-
-    newcomers: getStat('newcomers'),
-    certs:     getStat('certs'),
-    joiners:   getStat('joiners'),
-    actives:   getStat('actives'),
-    leavers:   getStat('leavers'),
-    revoked:  getStat('revoked'),
-    excluded:  getStat('excluded'),
-    ud:        getStat('ud'),
-    tx:        getStat('tx')
-  };
-
-  function getStat (statName) {
-    return () => co(function *() {
-      let stat = yield server.dal.getStat(statName);
-      return { result: new Stat(stat).json() };
-    });
-  }
-
-  this.promoted = (req) => co(function *() {
-    const number = yield ParametersService.getNumberP(req);
-    const promoted = yield BlockchainService.promoted(number);
-    return new Block(promoted).json();
-  });
-
-  this.blocks = (req) => co(function *() {
-    const params = ParametersService.getCountAndFrom(req);
-    const count = parseInt(params.count);
-    const from = parseInt(params.from);
-    let blocks = yield BlockchainService.blocksBetween(from, count);
-    blocks = blocks.map((b) => (new Block(b).json()));
-    return blocks;
-  });
-
-  this.current = () => co(function *() {
-    const current = yield server.dal.getCurrentBlockOrNull();
-    if (!current) throw constants.ERRORS.NO_CURRENT_BLOCK;
-    return new Block(current).json();
-  });
-
-  this.hardship = (req) => co(function *() {
-    let nextBlockNumber = 0;
-    const search = yield ParametersService.getSearchP(req);
-    const idty = yield IdentityService.findMemberWithoutMemberships(search);
-    if (!idty) {
-      throw constants.ERRORS.NO_MATCHING_IDENTITY;
-    }
-    if (!idty.member) {
-      throw constants.ERRORS.NOT_A_MEMBER;
-    }
-    const current = yield BlockchainService.current();
-    if (current) {
-      nextBlockNumber = current ? current.number + 1 : 0;
-    }
-    const difficulty = yield server.getBcContext().getIssuerPersonalizedDifficulty(idty.pubkey);
-    return {
-      "block": nextBlockNumber,
-      "level": difficulty
-    };
-  });
-
-  this.difficulties = () => co(function *() {
-    const current = yield server.dal.getCurrentBlockOrNull();
-    const number = (current && current.number) || 0;
-    const issuers = yield server.dal.getUniqueIssuersBetween(number - 1 - current.issuersFrame, number - 1);
-    const difficulties = [];
-    for (const issuer of issuers) {
-      const member = yield server.dal.getWrittenIdtyByPubkey(issuer);
-      const difficulty = yield server.getBcContext().getIssuerPersonalizedDifficulty(member.pubkey);
-      difficulties.push({
-        uid: member.uid,
-        level: difficulty
-      });
-    }
-    return {
-      "block": number + 1,
-      "levels": _.sortBy(difficulties, (diff) => diff.level)
-    };
-  });
-
-  this.memberships = (req) => co(function *() {
-    const search = yield ParametersService.getSearchP(req);
-    const idty = yield IdentityService.findMember(search);
-    const json = {
-      pubkey: idty.pubkey,
-      uid: idty.uid,
-      sigDate: idty.buid,
-      memberships: []
-    };
-    json.memberships = idty.memberships.map((msObj) => {
-      const ms = new Membership(msObj);
-      return {
-        version: ms.version,
-        currency: conf.currency,
-        membership: ms.membership,
-        blockNumber: parseInt(ms.blockNumber),
-        blockHash: ms.blockHash,
-        written: (!ms.written_number && ms.written_number !== 0) ? null : ms.written_number
-      };
-    });
-    json.memberships = _.sortBy(json.memberships, 'blockNumber');
-    json.memberships.reverse();
-    return json;
-  });
-
-  this.branches = () => co(function *() {
-    const branches = yield BlockchainService.branches();
-    const blocks = branches.map((b) => new Block(b).json());
-    return {
-      blocks: blocks
-    };
-  });
-}
diff --git a/app/controllers/network.js b/app/controllers/network.js
deleted file mode 100644
index 8aaf57fdf..000000000
--- a/app/controllers/network.js
+++ /dev/null
@@ -1,71 +0,0 @@
-"use strict";
-const _                = require('underscore');
-const co               = require('co');
-const http2raw         = require('../lib/helpers/http2raw');
-const constants        = require('../lib/constants');
-const Peer             = require('../lib/entity/peer');
-const AbstractController = require('./abstract');
-
-module.exports = function (server) {
-  return new NetworkBinding(server);
-};
-
-function NetworkBinding (server) {
-
-  AbstractController.call(this, server);
-
-  // Services
-  const MerkleService     = server.MerkleService;
-  const PeeringService    = server.PeeringService;
-
-  this.cert = PeeringService.cert;
-
-  this.peer = () => co(function *() {
-    const p = yield PeeringService.peer();
-    if (!p) {
-      throw constants.ERRORS.SELF_PEER_NOT_FOUND;
-    }
-    return p.json();
-  });
-
-  this.peersGet = (req) => co(function *() {
-    let merkle = yield server.dal.merkleForPeers();
-    return yield MerkleService.processForURL(req, merkle, (hashes) => {
-      return co(function *() {
-        try {
-          let peers = yield server.dal.findPeersWhoseHashIsIn(hashes);
-          const map = {};
-          peers.forEach((peer) => {
-            map[peer.hash] = Peer.statics.peerize(peer).json();
-          });
-          if (peers.length == 0) {
-            throw constants.ERRORS.PEER_NOT_FOUND;
-          }
-          return map;
-        } catch (e) {
-          throw e;
-        }
-      });
-    });
-  });
-
-  this.peersPost = (req) => this.pushEntity(req, http2raw.peer, constants.ENTITY_PEER);
-
-  this.peers = () => co(function *() {
-    let peers = yield server.dal.listAllPeers();
-    return {
-      peers: peers.map((p) => {
-        return _.pick(p,
-          'version',
-          'currency',
-          'status',
-          'first_down',
-          'last_try',
-          'pubkey',
-          'block',
-          'signature',
-          'endpoints');
-      })
-    };
-  });
-}
diff --git a/app/controllers/node.js b/app/controllers/node.js
deleted file mode 100644
index 4ebc3aba4..000000000
--- a/app/controllers/node.js
+++ /dev/null
@@ -1,38 +0,0 @@
-"use strict";
-
-const co = require('co');
-
-module.exports = function (server) {
-  return new NodeBinding(server);
-};
-
-function NodeBinding (server) {
-
-  this.summary = () => {
-    return {
-      "duniter": {
-        "software": "duniter",
-        "version": server.version,
-        "forkWindowSize": server.conf.forksize
-      }
-    };
-  };
-
-  this.sandboxes = () => co(function*() {
-    return {
-      identities: yield sandboxIt(server.dal.idtyDAL.sandbox),
-      certifications: yield sandboxIt(server.dal.certDAL.sandbox),
-      memberships: yield sandboxIt(server.dal.msDAL.sandbox),
-      transactions: yield sandboxIt(server.dal.txsDAL.sandbox)
-    };
-  });
-}
-
-function sandboxIt(sandbox) {
-  return co(function*() {
-    return {
-      size: sandbox.maxSize,
-      free: yield sandbox.getSandboxRoom()
-    };
-  });
-}
diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js
deleted file mode 100644
index b942455b6..000000000
--- a/app/controllers/transactions.js
+++ /dev/null
@@ -1,110 +0,0 @@
-"use strict";
-const co               = require('co');
-const _                = require('underscore');
-const http2raw         = require('../lib/helpers/http2raw');
-const Transaction      = require('../lib/entity/transaction');
-const constants        = require('../lib/constants');
-const AbstractController = require('./abstract');
-
-module.exports = function (server) {
-  return new TransactionBinding(server);
-};
-
-function TransactionBinding(server) {
-
-  AbstractController.call(this, server);
-
-  const conf = server.conf;
-
-  // Services
-  const ParametersService = server.ParametersService;
-
-  // Models
-  const Source = require('../lib/entity/source');
-
-  this.parseTransaction = (req) => this.pushEntity(req, http2raw.transaction, constants.ENTITY_TRANSACTION);
-
-  this.getSources = (req) => co(function *() {
-    const pubkey = yield ParametersService.getPubkeyP(req);
-    const sources = yield server.dal.getAvailableSourcesByPubkey(pubkey);
-    const result = {
-      "currency": conf.currency,
-      "pubkey": pubkey,
-      "sources": []
-    };
-    sources.forEach(function (src) {
-      result.sources.push(new Source(src).json());
-    });
-    return result;
-  });
-
-  this.getHistory = (req) => co(function *() {
-    const pubkey = yield ParametersService.getPubkeyP(req);
-    return getFilteredHistory(pubkey, (results) => results);
-  });
-
-  this.getHistoryBetweenBlocks = (req) => co(function *() {
-    const pubkey = yield ParametersService.getPubkeyP(req);
-    const from = yield ParametersService.getFromP(req);
-    const to = yield ParametersService.getToP(req);
-    return getFilteredHistory(pubkey, (res) => {
-      const histo = res.history;
-      histo.sent =     _.filter(histo.sent, function(tx){ return tx && tx.block_number >= from && tx.block_number <= to; });
-      histo.received = _.filter(histo.received, function(tx){ return tx && tx.block_number >= from && tx.block_number <= to; });
-      _.extend(histo, { sending: [], receiving: [] });
-      return res;
-    });
-  });
-
-  this.getHistoryBetweenTimes = (req) => co(function *() {
-    const pubkey = yield ParametersService.getPubkeyP(req);
-    const from = yield ParametersService.getFromP(req);
-    const to = yield ParametersService.getToP(req);
-    return getFilteredHistory(pubkey, (res) => {
-      const histo = res.history;
-      histo.sent =     _.filter(histo.sent, function(tx){ return tx && tx.time >= from && tx.time <= to; });
-      histo.received = _.filter(histo.received, function(tx){ return tx && tx.time >= from && tx.time <= to; });
-      _.extend(histo, { sending: [], receiving: [] });
-      return res;
-    });
-  });
-
-  this.getPendingForPubkey = (req) => co(function *() {
-    const pubkey = yield ParametersService.getPubkeyP(req);
-    return getFilteredHistory(pubkey, function(res) {
-      const histo = res.history;
-      _.extend(histo, { sent: [], received: [] });
-      return res;
-    });
-  });
-
-  this.getPending = () => co(function *() {
-    const pending = yield server.dal.getTransactionsPending();
-    const res = {
-      "currency": conf.currency,
-      "pending": pending
-    };
-    pending.map(function(tx, index) {
-      pending[index] = _.omit(new Transaction(tx).json(), 'currency', 'raw');
-    });
-    return res;
-  });
-
-  const getFilteredHistory = (pubkey, filter) => co(function*() {
-    let history = yield server.dal.getTransactionsHistory(pubkey);
-    let result = {
-      "currency": conf.currency,
-      "pubkey": pubkey,
-      "history": history
-    };
-    _.keys(history).map((key) => {
-      history[key].map((tx, index) => {
-        history[key][index] = _.omit(new Transaction(tx).json(), 'currency', 'raw');
-        _.extend(history[key][index], {block_number: tx && tx.block_number, time: tx && tx.time});
-      });
-    });
-    return filter(result);
-  });
-
-  return this;
-}
diff --git a/app/controllers/uds.js b/app/controllers/uds.js
deleted file mode 100644
index b8c4378ba..000000000
--- a/app/controllers/uds.js
+++ /dev/null
@@ -1,63 +0,0 @@
-"use strict";
-const co = require('co');
-const _ = require('underscore');
-
-module.exports = function (server) {
-  return new UDBinding(server);
-};
-
-function UDBinding(server) {
-
-  const conf = server.conf;
-
-  // Services
-  const ParametersService = server.ParametersService;
-
-  // Models
-  const Source = require('../lib/entity/source');
-
-  this.getHistory = (req) => co(function *() {
-    const pubkey = yield ParametersService.getPubkeyP(req);
-    return getUDSources(pubkey, (results) => results);
-  });
-
-  this.getHistoryBetweenBlocks = (req) => co(function *() {
-    const pubkey = yield ParametersService.getPubkeyP(req);
-    const from = yield ParametersService.getFromP(req);
-    const to = yield ParametersService.getToP(req);
-    return getUDSources(pubkey, (results) => {
-      results.history.history = _.filter(results.history.history, function(ud){ return ud.block_number >= from && ud.block_number <= to; });
-      return results;
-    });
-  });
-
-  this.getHistoryBetweenTimes = (req) => co(function *() {
-    const pubkey = yield ParametersService.getPubkeyP(req);
-    const from = yield ParametersService.getFromP(req);
-    const to = yield ParametersService.getToP(req);
-    return getUDSources(pubkey, (results) => {
-      results.history.history = _.filter(results.history.history, function(ud){ return ud.time >= from && ud.time <= to; });
-      return results;
-    });
-  });
-
-  function getUDSources(pubkey, filter) {
-    return co(function *() {
-      const history = yield server.dal.getUDHistory(pubkey);
-      const result = {
-        "currency": conf.currency,
-        "pubkey": pubkey,
-        "history": history
-      };
-      _.keys(history).map((key) => {
-        history[key].map((src, index) => {
-          history[key][index] = _.omit(new Source(src).UDjson(), 'currency', 'raw');
-          _.extend(history[key][index], { block_number: src && src.block_number, time: src && src.time });
-        });
-      });
-      return filter(result);
-    });
-  }
-  
-  return this;
-}
diff --git a/app/controllers/wot.js b/app/controllers/wot.js
deleted file mode 100644
index f60b97df4..000000000
--- a/app/controllers/wot.js
+++ /dev/null
@@ -1,242 +0,0 @@
-"use strict";
-const co = require('co');
-const _        = require('underscore');
-const http2raw = require('../lib/helpers/http2raw');
-const constants = require('../lib/constants');
-const AbstractController = require('./abstract');
-const logger   = require('../lib/logger')();
-
-module.exports = function (server) {
-  return new WOTBinding(server);
-};
-
-function WOTBinding (server) {
-
-  AbstractController.call(this, server);
-
-  const ParametersService = server.ParametersService;
-  const IdentityService   = server.IdentityService;
-  const BlockchainService   = server.BlockchainService;
-
-  const Identity = require('../lib/entity/identity');
-
-  this.lookup = (req) => co(function *() {
-    // Get the search parameter from HTTP query
-    const search = yield ParametersService.getSearchP(req);
-    // Make the research
-    const identities = yield IdentityService.searchIdentities(search);
-    // Entitify each result
-    identities.forEach((idty, index) => identities[index] = new Identity(idty));
-    // Prepare some data to avoid displaying expired certifications
-    for (const idty of identities) {
-      const certs = yield server.dal.certsToTarget(idty.pubkey, idty.getTargetHash());
-      const validCerts = [];
-      for (const cert of certs) {
-        const member = yield IdentityService.getWrittenByPubkey(cert.from);
-        if (member) {
-          cert.uids = [member.uid];
-          cert.isMember = member.member;
-          cert.wasMember = member.wasMember;
-        } else {
-          const potentials = yield IdentityService.getPendingFromPubkey(cert.from);
-          cert.uids = _(potentials).pluck('uid');
-          cert.isMember = false;
-          cert.wasMember = false;
-        }
-        validCerts.push(cert);
-      }
-      idty.certs = validCerts;
-      const signed = yield server.dal.certsFrom(idty.pubkey);
-      const validSigned = [];
-      for (let j = 0; j < signed.length; j++) {
-        const cert = _.clone(signed[j]);
-        cert.idty = yield server.dal.getIdentityByHashOrNull(cert.target);
-        if (cert.idty) {
-          validSigned.push(cert);
-        } else {
-          logger.debug('A certification to an unknown identity was found (%s => %s)', cert.from, cert.to);
-        }
-      }
-      idty.signed = validSigned;
-    }
-    if (identities.length == 0) {
-      throw constants.ERRORS.NO_MATCHING_IDENTITY;
-    }
-    const resultsByPubkey = {};
-    identities.forEach((identity) => {
-      const jsoned = identity.json();
-      if (!resultsByPubkey[jsoned.pubkey]) {
-        // Create the first matching identity with this pubkey in the map
-        resultsByPubkey[jsoned.pubkey] = jsoned;
-      } else {
-        // Merge the identity with the existing(s)
-        const existing = resultsByPubkey[jsoned.pubkey];
-        // We add the UID of the identity to the list of already added UIDs
-        existing.uids = existing.uids.concat(jsoned.uids);
-        // We do not merge the `signed`: every identity with the same pubkey has the same `signed` because it the *pubkey* which signs, not the identity
-      }
-    });
-    return {
-      partial: false,
-      results: Object.values(resultsByPubkey)
-    };
-  });
-
-  this.members = () => co(function *() {
-    const identities = yield server.dal.getMembers();
-    const json = {
-      results: []
-    };
-    identities.forEach((identity) => json.results.push({ pubkey: identity.pubkey, uid: identity.uid }));
-    return json;
-  });
-
-  this.certifiersOf = (req) => co(function *() {
-    const search = yield ParametersService.getSearchP(req);
-    const idty = yield IdentityService.findMemberWithoutMemberships(search);
-    const certs = yield server.dal.certsToTarget(idty.pubkey, idty.getTargetHash());
-    idty.certs = [];
-    for (const cert of certs) {
-      const certifier = yield server.dal.getWrittenIdtyByPubkey(cert.from);
-      if (certifier) {
-        cert.uid = certifier.uid;
-        cert.isMember = certifier.member;
-        cert.sigDate = certifier.buid;
-        cert.wasMember = true; // As we checked if(certified)
-        if (!cert.cert_time) {
-          let certBlock = yield server.dal.getBlock(cert.block_number);
-          cert.cert_time = {
-            block: certBlock.number,
-            medianTime: certBlock.medianTime
-          };
-        }
-        idty.certs.push(cert);
-      }
-    }
-    const json = {
-      pubkey: idty.pubkey,
-      uid: idty.uid,
-      sigDate: idty.buid,
-      isMember: idty.member,
-      certifications: []
-    };
-    idty.certs.forEach(function(cert){
-      json.certifications.push({
-        pubkey: cert.from,
-        uid: cert.uid,
-        isMember: cert.isMember,
-        wasMember: cert.wasMember,
-        cert_time: cert.cert_time,
-        sigDate: cert.sigDate,
-        written: cert.linked ? {
-          number: cert.written_block,
-          hash: cert.written_hash
-        } : null,
-        signature: cert.sig
-      });
-    });
-    return json;
-  });
-
-  this.requirements = (req) => co(function *() {
-    const search = yield ParametersService.getSearchP(req);
-    const identities = yield IdentityService.searchIdentities(search);
-    const all = yield BlockchainService.requirementsOfIdentities(identities);
-    if (!all || !all.length) {
-      throw constants.ERRORS.NO_IDTY_MATCHING_PUB_OR_UID;
-    }
-    return {
-      identities: all
-    };
-  });
-
-  this.certifiedBy = (req) => co(function *() {
-    const search = yield ParametersService.getSearchP(req);
-    const idty = yield IdentityService.findMemberWithoutMemberships(search);
-    const certs = yield server.dal.certsFrom(idty.pubkey);
-    idty.certs = [];
-    for (const cert of certs) {
-      const certified = yield server.dal.getWrittenIdtyByPubkey(cert.to);
-      if (certified) {
-        cert.uid = certified.uid;
-        cert.isMember = certified.member;
-        cert.sigDate = certified.buid;
-        cert.wasMember = true; // As we checked if(certified)
-        if (!cert.cert_time) {
-          let certBlock = yield server.dal.getBlock(cert.block_number);
-          cert.cert_time = {
-            block: certBlock.number,
-            medianTime: certBlock.medianTime
-          };
-        }
-        idty.certs.push(cert);
-      }
-    }
-    const json = {
-      pubkey: idty.pubkey,
-      uid: idty.uid,
-      sigDate: idty.buid,
-      isMember: idty.member,
-      certifications: []
-    };
-    idty.certs.forEach((cert) => json.certifications.push({
-        pubkey: cert.to,
-        uid: cert.uid,
-        isMember: cert.isMember,
-        wasMember: cert.wasMember,
-        cert_time: cert.cert_time,
-        sigDate: cert.sigDate,
-        written: cert.linked ? {
-          number: cert.written_block,
-          hash: cert.written_hash
-        } : null,
-        signature: cert.sig
-      })
-    );
-    return json;
-  });
-
-  this.identityOf = (req) => co(function *() {
-    let search = yield ParametersService.getSearchP(req);
-    let idty = yield IdentityService.findMemberWithoutMemberships(search);
-    if (!idty) {
-      throw 'Identity not found';
-    }
-    if (!idty.member) {
-      throw 'Not a member';
-    }
-    return {
-      pubkey: idty.pubkey,
-      uid: idty.uid,
-      sigDate: idty.buid
-    };
-  });
-
-  this.add = (req) => this.pushEntity(req, http2raw.identity, constants.ENTITY_IDENTITY);
-
-  this.certify = (req) => this.pushEntity(req, http2raw.certification, constants.ENTITY_CERTIFICATION);
-
-  this.revoke = (req) => this.pushEntity(req, http2raw.revocation, constants.ENTITY_REVOCATION);
-
-  this.pendingMemberships = () => co(function*() {
-    const memberships = yield server.dal.findNewcomers();
-    const json = {
-      memberships: []
-    };
-    json.memberships = memberships.map((ms) => {
-      return {
-        pubkey: ms.issuer,
-        uid: ms.userid,
-        version: ms.version,
-        currency: server.conf.currency,
-        membership: ms.membership,
-        blockNumber: parseInt(ms.blockNumber),
-        blockHash: ms.blockHash,
-        written: (!ms.written_number && ms.written_number !== 0) ? null : ms.written_number
-      };
-    });
-    json.memberships = _.sortBy(json.memberships, 'blockNumber');
-    json.memberships.reverse();
-    return json;
-  });
-}
diff --git a/app/lib/constants.js b/app/lib/constants.js
index 3b5c2fa71..091b6ef11 100644
--- a/app/lib/constants.js
+++ b/app/lib/constants.js
@@ -32,14 +32,6 @@ const MAXIMUM_LEN_OF_COMPACT_TX = 100;
 
 module.exports = {
 
-  ENTITY_TRANSACTION: 'transaction',
-  ENTITY_BLOCK: 'block',
-  ENTITY_MEMBERSHIP: 'membership',
-  ENTITY_PEER: 'peer',
-  ENTITY_IDENTITY: 'identity',
-  ENTITY_CERTIFICATION: 'certification',
-  ENTITY_REVOCATION: 'revocation',
-
   ERROR: {
 
     PEER: {
@@ -59,7 +51,6 @@ module.exports = {
     SIGNATURE_DOES_NOT_MATCH:             { httpCode: 400, uerr: { ucode: 1003, message: "Signature does not match" }},
     ALREADY_UP_TO_DATE:                   { httpCode: 400, uerr: { ucode: 1004, message: "Already up-to-date" }},
     WRONG_DOCUMENT:                       { httpCode: 400, uerr: { ucode: 1005, message: "Document has unkown fields or wrong line ending format" }},
-    HTTP_LIMITATION:                      { httpCode: 503, uerr: { ucode: 1006, message: "This URI has reached its maximum usage quota. Please retry later." }},
     SANDBOX_FOR_IDENTITY_IS_FULL:         { httpCode: 503, uerr: { ucode: 1007, message: "The identities' sandbox is full. Please retry with another document or retry later." }},
     SANDBOX_FOR_CERT_IS_FULL:             { httpCode: 503, uerr: { ucode: 1008, message: "The certifications' sandbox is full. Please retry with another document or retry later." }},
     SANDBOX_FOR_MEMERSHIP_IS_FULL:        { httpCode: 503, uerr: { ucode: 1009, message: "The memberships' sandbox is full. Please retry with another document or retry later." }},
@@ -69,31 +60,16 @@ module.exports = {
     CLI_CALLERR_RESET:                    { httpCode: 503, uerr: { ucode: 1013, message: "Bad command: usage is `reset config`, `reset data`, `reset peers`, `reset stats` or `reset all`" }},
     CLI_CALLERR_CONFIG:                   { httpCode: 503, uerr: { ucode: 1014, message: "Bad command: usage is `config`." }},
 
-    HTTP_PARAM_PUBKEY_REQUIRED:           { httpCode: 400, uerr: { ucode: 1101, message: "Parameter `pubkey` is required" }},
-    HTTP_PARAM_IDENTITY_REQUIRED:         { httpCode: 400, uerr: { ucode: 1102, message: "Parameter `identity` is required" }},
-    HTTP_PARAM_PEER_REQUIRED:             { httpCode: 400, uerr: { ucode: 1103, message: "Requires a peer" }},
-    HTTP_PARAM_BLOCK_REQUIRED:            { httpCode: 400, uerr: { ucode: 1104, message: "Requires a block" }},
-    HTTP_PARAM_MEMBERSHIP_REQUIRED:       { httpCode: 400, uerr: { ucode: 1105, message: "Requires a membership" }},
-    HTTP_PARAM_TX_REQUIRED:               { httpCode: 400, uerr: { ucode: 1106, message: "Requires a transaction" }},
-    HTTP_PARAM_SIG_REQUIRED:              { httpCode: 400, uerr: { ucode: 1107, message: "Parameter `sig` is required" }},
-    HTTP_PARAM_CERT_REQUIRED:             { httpCode: 400, uerr: { ucode: 1108, message: "Parameter `cert` is required" }},
-    HTTP_PARAM_REVOCATION_REQUIRED:       { httpCode: 400, uerr: { ucode: 1109, message: "Parameter `revocation` is required" }},
-    HTTP_PARAM_CONF_REQUIRED:             { httpCode: 400, uerr: { ucode: 1110, message: "Parameter `conf` is required" }},
-    HTTP_PARAM_CPU_REQUIRED:              { httpCode: 400, uerr: { ucode: 1111, message: "Parameter `cpu` is required" }},
-
     // Business errors
     NO_MATCHING_IDENTITY:                 { httpCode: 404, uerr: { ucode: 2001, message: "No matching identity" }},
     UID_ALREADY_USED:                     { httpCode: 400, uerr: { ucode: 2002, message: "UID already used in the blockchain" }},
     PUBKEY_ALREADY_USED:                  { httpCode: 400, uerr: { ucode: 2003, message: "Pubkey already used in the blockchain" }},
     NO_MEMBER_MATCHING_PUB_OR_UID:        { httpCode: 404, uerr: { ucode: 2004, message: "No member matching this pubkey or uid" }},
-    SELF_PEER_NOT_FOUND:                  { httpCode: 404, uerr: { ucode: 2005, message: "Self peering was not found" }},
     WRONG_SIGNATURE_MEMBERSHIP:           { httpCode: 400, uerr: { ucode: 2006, message: "wrong signature for membership" }},
     ALREADY_RECEIVED_MEMBERSHIP:          { httpCode: 400, uerr: { ucode: 2007, message: "Already received membership" }},
     MEMBERSHIP_A_NON_MEMBER_CANNOT_LEAVE: { httpCode: 400, uerr: { ucode: 2008, message: "A non-member cannot leave" }},
     NOT_A_MEMBER:                         { httpCode: 400, uerr: { ucode: 2009, message: "Not a member" }},
-    NO_CURRENT_BLOCK:                     { httpCode: 404, uerr: { ucode: 2010, message: "No current block" }},
     BLOCK_NOT_FOUND:                      { httpCode: 404, uerr: { ucode: 2011, message: "Block not found" }},
-    PEER_NOT_FOUND:                       { httpCode: 404, uerr: { ucode: 2012, message: "Peer not found" }},
     WRONG_UNLOCKER:                       { httpCode: 400, uerr: { ucode: 2013, message: "Wrong unlocker in transaction" }},
     LOCKTIME_PREVENT:                     { httpCode: 400, uerr: { ucode: 2014, message: "Locktime not elapsed yet" }},
     SOURCE_ALREADY_CONSUMED:              { httpCode: 400, uerr: { ucode: 2015, message: "Source already consumed" }},
@@ -250,14 +226,6 @@ module.exports = {
     MAX_CONCURRENT_POST: 3,
     DEFAULT_TIMEOUT: 10 * 1000, // 10 seconds
     SYNC_LONG_TIMEOUT: 30 * 1000, // 30 seconds
-    DEFAULT_PORT: 8999,
-    PORT: {
-      START: 15000
-    },
-    UPNP: {
-      INTERVAL: 300,
-      TTL: 600
-    },
     SYNC: {
       MAX: 20
     },
diff --git a/app/lib/contacter.js b/app/lib/contacter.js
index 9187a4483..fcb34cfdd 100644
--- a/app/lib/contacter.js
+++ b/app/lib/contacter.js
@@ -3,8 +3,8 @@
 const co = require('co');
 const rp = require('request-promise');
 const constants = require('./constants');
-const sanitize = require('./streams/sanitize');
-const dtos = require('./streams/dtos');
+const sanitize = require('duniter-bma').duniter.methods.sanitize;
+const dtos = require('duniter-bma').duniter.methods.dtos;
 
 /**
  * Created by cgeek on 16/10/16.
diff --git a/app/lib/entity/configuration.js b/app/lib/entity/configuration.js
index acec9a379..5749d9377 100644
--- a/app/lib/entity/configuration.js
+++ b/app/lib/entity/configuration.js
@@ -5,13 +5,6 @@ const constants = require('../constants');
 const defaultConf = function() {
   return {
     "currency": null,
-    "port": constants.NETWORK.DEFAULT_PORT,
-    "ipv4": "127.0.0.1",
-    "ipv6": null,
-    "remotehost": null,
-    "remoteipv4": null,
-    "remoteipv6": null,
-    "remoteport": constants.NETWORK.DEFAULT_PORT,
     "endpoints": [],
     "rmEndpoints": [],
     "cpu": constants.DEFAULT_CPU,
diff --git a/app/lib/helpers/http2raw.js b/app/lib/helpers/http2raw.js
deleted file mode 100644
index 76580f190..000000000
--- a/app/lib/helpers/http2raw.js
+++ /dev/null
@@ -1,38 +0,0 @@
-"use strict";
-
-const constants = require('../constants');
-
-module.exports = {
-  identity:      requiresParameter('identity',    constants.ERRORS.HTTP_PARAM_IDENTITY_REQUIRED),
-  certification: requiresParameter('cert',        constants.ERRORS.HTTP_PARAM_CERT_REQUIRED),
-  revocation:    requiresParameter('revocation',  constants.ERRORS.HTTP_PARAM_REVOCATION_REQUIRED),
-  transaction:   requiresParameter('transaction', constants.ERRORS.HTTP_PARAM_TX_REQUIRED),
-  peer:          requiresParameter('peer',        constants.ERRORS.HTTP_PARAM_PEER_REQUIRED),
-  membership:    Http2RawMembership,
-  block:         requiresParameter('block',       constants.ERRORS.HTTP_PARAM_BLOCK_REQUIRED),
-  conf:          requiresParameter('conf',        constants.ERRORS.HTTP_PARAM_CONF_REQUIRED),
-  cpu:           requiresParameter('cpu',         constants.ERRORS.HTTP_PARAM_CPU_REQUIRED)
-};
-
-function requiresParameter(parameter, err) {
-  return (req) => {
-    if(!req.body || req.body[parameter] === undefined){
-      throw err;
-    }
-    return req.body[parameter];
-  };
-}
-
-function Http2RawMembership (req) {
-  if(!(req.body && req.body.membership)){
-    throw constants.ERRORS.HTTP_PARAM_MEMBERSHIP_REQUIRED;
-  }
-  let ms = req.body.membership;
-  if(req.body && req.body.signature){
-    ms = [ms, req.body.signature].join('');
-    if (!ms.match(/\n$/)) {
-      ms += '\n';
-    }
-  }
-  return ms;
-}
diff --git a/app/lib/helpers/http400.js b/app/lib/helpers/http400.js
deleted file mode 100644
index 5029d40cc..000000000
--- a/app/lib/helpers/http400.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-const logger = require('../logger')('http');
-
-module.exports = function http400 (res) {
-  return function (err) {
-    logger.warn(err);
-    res.send(400, err);
-  };
-}
diff --git a/app/lib/helpers/parameters.js b/app/lib/helpers/parameters.js
deleted file mode 100644
index 2bb664b68..000000000
--- a/app/lib/helpers/parameters.js
+++ /dev/null
@@ -1,101 +0,0 @@
-"use strict";
-const Q = require('q');
-const constants = require('../constants');
-
-module.exports = function () {
-  return new ParameterNamespace();
-};
-
-function ParameterNamespace () {
-
-  this.getSearch = function (req, callback) {
-    if(!req.params || !req.params.search){
-      callback("No search criteria given");
-      return;
-    }
-    callback(null, req.params.search);
-  };
-
-  this.getSearchP = (req) => Q.nbind(this.getSearch, this)(req);
-
-  this.getCountAndFrom = function (req){
-    if(!req.params.from){
-      throw "From is required";
-    }
-    if(!req.params.count){
-      throw "Count is required";
-    }
-    const matches = req.params.from.match(/^(\d+)$/);
-    if(!matches){
-      throw "From format is incorrect, must be a positive integer";
-    }
-    const matches2 = req.params.count.match(/^(\d+)$/);
-    if(!matches2){
-      throw "Count format is incorrect, must be a positive integer";
-    }
-    return {
-      count: matches2[1],
-      from: matches[1]
-    };
-  };
-
-  this.getPubkey = function (req, callback){
-    if(!req.params.pubkey){
-      callback('Parameter `pubkey` is required');
-      return;
-    }
-    const matches = req.params.pubkey.match(constants.PUBLIC_KEY);
-    if(!matches){
-      callback("Pubkey format is incorrect, must be a Base58 string");
-      return;
-    }
-    callback(null, matches[0]);
-  };
-
-  this.getPubkeyP = (req) => Q.nbind(this.getPubkey, this)(req);
-
-  this.getFrom = function (req, callback){
-    if(!req.params.from){
-      callback('Parameter `from` is required');
-      return;
-    }
-    const matches = req.params.from.match(/^(\d+)$/);
-    if(!matches){
-      callback("From format is incorrect, must be a positive or zero integer");
-      return;
-    }
-    callback(null, matches[0]);
-  };
-
-  this.getFromP = (req) => Q.nbind(this.getFrom, this)(req);
-
-  this.getTo = function (req, callback){
-    if(!req.params.to){
-      callback('Parameter `to` is required');
-      return;
-    }
-    const matches = req.params.to.match(/^(\d+)$/);
-    if(!matches){
-      callback("To format is incorrect, must be a positive or zero integer");
-      return;
-    }
-    callback(null, matches[0]);
-  };
-
-  this.getToP = (req) => Q.nbind(this.getTo, this)(req);
-
-  this.getNumber = function (req, callback){
-    if(!req.params.number){
-      callback("Number is required");
-      return;
-    }
-    const matches = req.params.number.match(/^(\d+)$/);
-    if(!matches){
-      callback("Number format is incorrect, must be a positive integer");
-      return;
-    }
-    callback(null, parseInt(matches[1]));
-  };
-
-  this.getNumberP = (req) => Q.nbind(this.getNumber, this)(req);
-}
diff --git a/app/lib/streams/bma.js b/app/lib/streams/bma.js
deleted file mode 100644
index 7d1158749..000000000
--- a/app/lib/streams/bma.js
+++ /dev/null
@@ -1,31 +0,0 @@
-"use strict";
-
-const network = require('../system/network');
-const routes = require('./routes');
-
-module.exports = function(server, interfaces, httpLogs) {
-
-  if (!interfaces) {
-    interfaces = [];
-    if (server.conf) {
-      if (server.conf.ipv4) {
-        interfaces = [{
-          ip: server.conf.ipv4,
-          port: server.conf.port
-        }];
-      }
-      if (server.conf.ipv6) {
-        interfaces.push({
-          ip: server.conf.ipv6,
-          port: (server.conf.remoteport || server.conf.port) // We try to get the best one
-        });
-      }
-    }
-  }
-
-  return network.createServersAndListen('Duniter server', interfaces, httpLogs, null, (app, httpMethods) => {
-    
-    routes.bma(server, '', app, httpMethods);
-
-  }, routes.bmaWS(server, ''));
-};
diff --git a/app/lib/streams/dtos.js b/app/lib/streams/dtos.js
deleted file mode 100644
index e39137068..000000000
--- a/app/lib/streams/dtos.js
+++ /dev/null
@@ -1,449 +0,0 @@
-"use strict";
-
-let dtos;
-
-module.exports = dtos = {};
-
-dtos.Summary = {
-  duniter: {
-    "software": String,
-    "version": String,
-    "forkWindowSize": Number
-  }
-};
-
-dtos.Parameters = {
-  currency: String,
-  c: Number,
-  dt: Number,
-  ud0: Number,
-  sigPeriod: Number,
-  sigStock: Number,
-  sigWindow: Number,
-  sigValidity: Number,
-  sigQty: Number,
-  idtyWindow: Number,
-  msWindow: Number,
-  xpercent: Number,
-  msValidity: Number,
-  stepMax: Number,
-  medianTimeBlocks: Number,
-  avgGenTime: Number,
-  dtDiffEval: Number,
-  percentRot: Number
-};
-
-dtos.Membership = {
-  "signature": String,
-  "membership": {
-    "version": Number,
-    "currency": String,
-    "issuer": String,
-    "membership": String,
-    "date": Number,
-    "sigDate": Number,
-    "raw": String
-  }
-};
-
-dtos.Memberships = {
-  "pubkey": String,
-  "uid": String,
-  "sigDate": String,
-  "memberships": [
-    {
-      "version": Number,
-      "currency": String,
-      "membership": String,
-      "blockNumber": Number,
-      "blockHash": String,
-      "written": Number
-    }
-  ]
-};
-
-dtos.MembershipList = {
-  "memberships": [
-    {
-      "pubkey": String,
-      "uid": String,
-      "version": Number,
-      "currency": String,
-      "membership": String,
-      "blockNumber": Number,
-      "blockHash": String,
-      "written": Number
-    }
-  ]
-};
-
-dtos.TransactionOfBlock = {
-  "version": Number,
-  "currency": String,
-  "comment": String,
-  "locktime": Number,
-  "signatures": [String],
-  "outputs": [String],
-  "inputs": [String],
-  "unlocks": [String],
-  "block_number": Number,
-  "blockstamp": String,
-  "blockstampTime": Number,
-  "time": Number,
-  "issuers": [String]
-};
-
-dtos.Block = {
-  "version": Number,
-  "currency": String,
-  "number": Number,
-  "issuer": String,
-  "issuersFrame": Number,
-  "issuersFrameVar": Number,
-  "issuersCount": Number,
-  "parameters": String,
-  "membersCount": Number,
-  "monetaryMass": Number,
-  "powMin": Number,
-  "time": Number,
-  "medianTime": Number,
-  "dividend": Number,
-  "unitbase": Number,
-  "hash": String,
-  "previousHash": String,
-  "previousIssuer": String,
-  "identities": [String],
-  "certifications": [String],
-  "joiners": [String],
-  "actives": [String],
-  "leavers": [String],
-  "revoked": [String],
-  "excluded": [String],
-  "transactions": [dtos.TransactionOfBlock],
-  "nonce": Number,
-  "inner_hash": String,
-  "signature": String,
-  "raw": String
-};
-
-dtos.Hardship = {
-  "block": Number,
-  "level": Number
-};
-
-dtos.Difficulty = {
-  "uid": String,
-  "level": Number
-};
-
-dtos.Difficulties = {
-  "block": Number,
-  "levels": [dtos.Difficulty]
-};
-
-dtos.Blocks = [dtos.Block];
-
-dtos.Stat = {
-  "result": {
-    "blocks": [Number]
-  }
-};
-
-dtos.Branches = {
-  "blocks": [dtos.Block]
-};
-
-dtos.Peer = {
-  "version": Number,
-  "currency": String,
-  "pubkey": String,
-  "block": String,
-  "endpoints": [String],
-  "signature": String,
-  "raw": String
-};
-
-dtos.DBPeer = {
-  "version": Number,
-  "currency": String,
-  "pubkey": String,
-  "block": String,
-  "status": String,
-  "first_down": Number,
-  "last_try": Number,
-  "endpoints": [String],
-  "signature": String,
-  "raw": String
-};
-
-dtos.Peers = {
-  "peers": [dtos.DBPeer]
-};
-
-dtos.MerkleOfPeers = {
-  "depth": Number,
-  "nodesCount": Number,
-  "leavesCount": Number,
-  "root": String,
-  "leaves": [String],
-  "leaf": {
-    "hash": String,
-    "value": dtos.DBPeer
-  }
-};
-
-dtos.Other = {
-  "pubkey": String,
-  "meta": {
-    "block_number": Number,
-    "block_hash": String
-  },
-  "uids": [String],
-  "isMember": Boolean,
-  "wasMember": Boolean,
-  "signature": String
-};
-
-dtos.UID = {
-  "uid": String,
-  "meta": {
-    "timestamp": String
-  },
-  "self": String,
-  "revocation_sig": String,
-  "revoked": Boolean,
-  "revoked_on": Number,
-  "others": [dtos.Other]
-};
-
-dtos.Signed = {
-  "uid": String,
-  "pubkey": String,
-  "meta": {
-    "timestamp": String
-  },
-  "cert_time": {
-    "block": Number,
-    "block_hash": String
-  },
-  "isMember": Boolean,
-  "wasMember": Boolean,
-  "signature": String
-};
-
-dtos.CertIdentity = {
-  "issuer": String,
-  "uid": String,
-  "timestamp": String,
-  "sig": String
-};
-
-dtos.Cert = {
-  "issuer": String,
-  "timestamp": String,
-  "sig": String,
-  "target": dtos.CertIdentity
-};
-
-dtos.Identity = {
-  "pubkey": String,
-  "uids": [dtos.UID],
-  "signed": [dtos.Signed]
-};
-
-dtos.Result = {
-  "result": Boolean
-};
-
-dtos.Lookup = {
-  "partial": Boolean,
-  "results": [dtos.Identity]
-};
-
-dtos.Members = {
-  "results": [{
-    pubkey: String,
-    uid: String
-  }]
-};
-
-dtos.RequirementsCert = {
-  from: String,
-  to: String,
-  expiresIn: Number
-};
-
-dtos.Requirements = {
-  "identities": [{
-    pubkey: String,
-    uid: String,
-    meta: {
-      timestamp: String
-    },
-    expired: Boolean,
-    outdistanced: Boolean,
-    certifications: [dtos.RequirementsCert],
-    membershipPendingExpiresIn: Number,
-    membershipExpiresIn: Number
-  }]
-};
-
-dtos.Certification = {
-  "pubkey": String,
-  "uid": String,
-  "isMember": Boolean,
-  "wasMember": Boolean,
-  "cert_time": {
-    "block": Number,
-    "medianTime": Number
-  },
-  "sigDate": String,
-  "written": {
-    "number": Number,
-    "hash": String
-  },
-  "signature": String
-};
-
-dtos.Certifications = {
-  "pubkey": String,
-  "uid": String,
-  "sigDate": String,
-  "isMember": Boolean,
-  "certifications": [dtos.Certification]
-};
-
-dtos.SimpleIdentity = {
-  "pubkey": String,
-  "uid": String,
-  "sigDate": String
-};
-
-dtos.Transaction = {
-  "version": Number,
-  "currency": String,
-  "issuers": [String],
-  "inputs": [String],
-  "unlocks": [String],
-  "outputs": [String],
-  "comment": String,
-  "locktime": Number,
-  "signatures": [String],
-  "raw": String,
-  "hash": String
-};
-
-dtos.Source = {
-  "type": String,
-  "noffset": Number,
-  "identifier": String,
-  "amount": Number,
-  "base": Number
-};
-
-dtos.Sources = {
-  "currency": String,
-  "pubkey": String,
-  "sources": [dtos.Source]
-};
-
-dtos.TxOfHistory = {
-  "version": Number,
-  "issuers": [String],
-  "inputs": [String],
-  "unlocks": [String],
-  "outputs": [String],
-  "comment": String,
-  "locktime": Number,
-  "received": Number,
-  "signatures": [String],
-  "hash": String,
-  "block_number": Number,
-  "time": Number,
-  "blockstamp": String,
-  "blockstampTime": Number
-};
-
-dtos.TxHistory = {
-  "currency": String,
-  "pubkey": String,
-  "history": {
-    "sent": [dtos.TxOfHistory],
-    "received": [dtos.TxOfHistory],
-    "sending": [dtos.TxOfHistory],
-    "receiving": [dtos.TxOfHistory],
-    "pending": [dtos.TxOfHistory]
-  }
-};
-
-dtos.TxPending = {
-  "currency": String,
-  "pending": [dtos.Transaction]
-};
-
-dtos.UD = {
-  "block_number": Number,
-  "consumed": Boolean,
-  "time": Number,
-  "amount": Number,
-  "base": Number
-};
-
-dtos.UDHistory = {
-  "currency": String,
-  "pubkey": String,
-  "history": {
-    "history": [dtos.UD]
-  }
-};
-
-dtos.Boolean = {
-  "success": Boolean
-};
-
-dtos.SummaryConf = {
-  "cpu": Number
-};
-
-dtos.AdminSummary = {
-  "version": String,
-  "host": String,
-  "current": dtos.Block,
-  "rootBlock": dtos.Block,
-  "pubkey": String,
-  "seckey": String,
-  "conf": dtos.SummaryConf,
-  "parameters": dtos.Parameters,
-  "lastUDBlock": dtos.Block
-};
-
-dtos.PoWSummary = {
-  "total": Number,
-  "mirror": Boolean,
-  "waiting": Boolean
-};
-
-dtos.PreviewPubkey = {
-  "pubkey": String
-};
-
-dtos.Sandbox = {
-  size: Number,
-  free: Number
-};
-
-dtos.IdentitySandbox = dtos.Sandbox;
-dtos.CertificationSandbox = dtos.Sandbox;
-dtos.MembershipSandbox = dtos.Sandbox;
-dtos.TransactionSandbox = dtos.Sandbox;
-
-dtos.Sandboxes = {
-  identities: dtos.IdentitySandbox,
-  certifications: dtos.CertificationSandbox,
-  memberships: dtos.MembershipSandbox,
-  transactions: dtos.TransactionSandbox
-};
-
-dtos.LogLink = {
-  link: String
-};
diff --git a/app/lib/streams/jsoner.js b/app/lib/streams/jsoner.js
deleted file mode 100644
index e24820a3b..000000000
--- a/app/lib/streams/jsoner.js
+++ /dev/null
@@ -1,21 +0,0 @@
-"use strict";
-const util     = require('util');
-const stream   = require('stream');
-
-module.exports = function () {
-  return new JSONer();
-};
-
-function JSONer () {
-
-  stream.Transform.call(this, { objectMode: true });
-
-  const that = this;
-
-  this._write = function (entity, enc, done) {
-    that.push(entity.json());
-    done();
-  };
-}
-
-util.inherits(JSONer, stream.Transform);
diff --git a/app/lib/streams/routes.js b/app/lib/streams/routes.js
deleted file mode 100644
index 39b980d1b..000000000
--- a/app/lib/streams/routes.js
+++ /dev/null
@@ -1,125 +0,0 @@
-"use strict";
-
-const co = require('co');
-const es = require('event-stream');
-const dtos = require('./dtos');
-const sanitize = require('./sanitize');
-const limiter = require('../system/limiter');
-const logger = require('../logger')('routes');
-
-const WebSocketServer = require('ws').Server;
-
-module.exports = {
-
-  bma: function(server, prefix, app, httpMethods) {
-
-    const node         = require('../../controllers/node')(server);
-    const blockchain   = require('../../controllers/blockchain')(server);
-    const net          = require('../../controllers/network')(server, server.conf);
-    const wot          = require('../../controllers/wot')(server);
-    const transactions = require('../../controllers/transactions')(server);
-    const dividend     = require('../../controllers/uds')(server);
-    httpMethods.httpGET(  prefix + '/',                                      node.summary,                         dtos.Summary,        limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/node/summary',                          node.summary,                         dtos.Summary,        limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/node/sandboxes',                        node.sandboxes,                       dtos.Sandboxes,      limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/parameters',                 blockchain.parameters,                dtos.Parameters,     limiter.limitAsHighUsage());
-    httpMethods.httpPOST( prefix + '/blockchain/membership',                 blockchain.parseMembership,           dtos.Membership,     limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/memberships/:search',        blockchain.memberships,               dtos.Memberships,    limiter.limitAsHighUsage());
-    httpMethods.httpPOST( prefix + '/blockchain/block',                      blockchain.parseBlock,                dtos.Block,          limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/block/:number',              blockchain.promoted,                  dtos.Block,          limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/blocks/:count/:from',        blockchain.blocks,                    dtos.Blocks,         limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/current',                    blockchain.current,                   dtos.Block,          limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/hardship/:search',           blockchain.hardship,                  dtos.Hardship,       limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/difficulties',               blockchain.difficulties,              dtos.Difficulties,   limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/newcomers',             blockchain.with.newcomers,            dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/certs',                 blockchain.with.certs,                dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/joiners',               blockchain.with.joiners,              dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/actives',               blockchain.with.actives,              dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/leavers',               blockchain.with.leavers,              dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/excluded',              blockchain.with.excluded,             dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/revoked',               blockchain.with.revoked,              dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/ud',                    blockchain.with.ud,                   dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/with/tx',                    blockchain.with.tx,                   dtos.Stat,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/blockchain/branches',                   blockchain.branches,                  dtos.Branches,       limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/network/peering',                       net.peer,                             dtos.Peer,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/network/peering/peers',                 net.peersGet,                         dtos.MerkleOfPeers,  limiter.limitAsVeryHighUsage());
-    httpMethods.httpPOST( prefix + '/network/peering/peers',                 net.peersPost,                        dtos.Peer,           limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/network/peers',                         net.peers,                            dtos.Peers,          limiter.limitAsHighUsage());
-    httpMethods.httpPOST( prefix + '/wot/add',                               wot.add,                              dtos.Identity,       limiter.limitAsHighUsage());
-    httpMethods.httpPOST( prefix + '/wot/certify',                           wot.certify,                          dtos.Cert,           limiter.limitAsHighUsage());
-    httpMethods.httpPOST( prefix + '/wot/revoke',                            wot.revoke,                           dtos.Result,         limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/wot/lookup/:search',                    wot.lookup,                           dtos.Lookup,         limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/wot/members',                           wot.members,                          dtos.Members,        limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/wot/pending',                           wot.pendingMemberships,               dtos.MembershipList, limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/wot/requirements/:search',              wot.requirements,                     dtos.Requirements,   limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/wot/certifiers-of/:search',             wot.certifiersOf,                     dtos.Certifications, limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/wot/certified-by/:search',              wot.certifiedBy,                      dtos.Certifications, limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/wot/identity-of/:search',               wot.identityOf,                       dtos.SimpleIdentity, limiter.limitAsHighUsage());
-    httpMethods.httpPOST( prefix + '/tx/process',                            transactions.parseTransaction,        dtos.Transaction,    limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/tx/sources/:pubkey',                    transactions.getSources,              dtos.Sources,        limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/tx/history/:pubkey',                    transactions.getHistory,              dtos.TxHistory,      limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/tx/history/:pubkey/blocks/:from/:to',   transactions.getHistoryBetweenBlocks, dtos.TxHistory,      limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/tx/history/:pubkey/times/:from/:to',    transactions.getHistoryBetweenTimes,  dtos.TxHistory,      limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/tx/history/:pubkey/pending',            transactions.getPendingForPubkey,     dtos.TxHistory,      limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/tx/pending',                            transactions.getPending,              dtos.TxPending,      limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/ud/history/:pubkey',                    dividend.getHistory,                  dtos.UDHistory,      limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/ud/history/:pubkey/blocks/:from/:to',   dividend.getHistoryBetweenBlocks,     dtos.UDHistory,      limiter.limitAsHighUsage());
-    httpMethods.httpGET(  prefix + '/ud/history/:pubkey/times/:from/:to',    dividend.getHistoryBetweenTimes,      dtos.UDHistory,      limiter.limitAsHighUsage());
-  },
-  
-  bmaWS: function(server, prefix) {
-    return (httpServer) => {
-
-      let currentBlock = {};
-      let wssBlock = new WebSocketServer({
-        server: httpServer,
-        path: prefix + '/ws/block'
-      });
-      let wssPeer = new WebSocketServer({
-        server: httpServer,
-        path: prefix + '/ws/peer'
-      });
-
-      wssBlock.on('error', function (error) {
-        logger.error('Error on WS Server');
-        logger.error(error);
-      });
-
-      wssBlock.on('connection', function connection(ws) {
-        co(function *() {
-          currentBlock = yield server.dal.getCurrentBlockOrNull();
-          if (currentBlock) {
-            ws.send(JSON.stringify(sanitize(currentBlock, dtos.Block)));
-          }
-        });
-      });
-
-      wssBlock.broadcast = (data) => wssBlock.clients.forEach((client) => {
-        try {
-          client.send(data);
-        } catch (e) {
-          logger.error('error on ws: %s', e);
-        }
-      });
-      wssPeer.broadcast = (data) => wssPeer.clients.forEach((client) => client.send(data));
-
-      // Forward blocks & peers
-      server
-        .pipe(es.mapSync(function(data) {
-          try {
-            // Broadcast block
-            if (data.joiners) {
-              currentBlock = data;
-              wssBlock.broadcast(JSON.stringify(sanitize(currentBlock, dtos.Block)));
-            }
-            // Broadcast peer
-            if (data.endpoints) {
-              wssPeer.broadcast(JSON.stringify(sanitize(data, dtos.Peer)));
-            }
-          } catch (e) {
-            logger.error('error on ws mapSync:', e);
-          }
-        }));
-    };
-  }
-};
diff --git a/app/lib/streams/sanitize.js b/app/lib/streams/sanitize.js
deleted file mode 100644
index c36b3bbc8..000000000
--- a/app/lib/streams/sanitize.js
+++ /dev/null
@@ -1,118 +0,0 @@
-"use strict";
-
-let _ = require('underscore');
-
-module.exports = function sanitize (json, contract) {
-
-  // Tries to sanitize only if contract is given
-  if (contract) {
-
-    if (Object.prototype.toString.call(contract) === "[object Array]") {
-      // Contract is an array
-
-      if (Object.prototype.toString.call(json) !== "[object Array]") {
-        json = [];
-      }
-
-      for (let i = 0, len = json.length; i < len; i++) {
-        json[i] = sanitize(json[i], contract[0]);
-      }
-    } else {
-      // Contract is an object or native type
-
-      // Return type is either a string, a number or an object
-      if (typeof json != typeof contract) {
-        try {
-          // Cast value
-          json = contract(json);
-        } catch (e) {
-          // Cannot be casted: create empty value
-          json = contract();
-        }
-      }
-
-      let contractFields = _(contract).keys();
-      let objectFields = _(json).keys();
-      let toDeleteFromObj = _.difference(objectFields, contractFields);
-
-      // Remove unwanted fields
-      for (let i = 0, len = toDeleteFromObj.length; i < len; i++) {
-        let field = toDeleteFromObj[i];
-        delete json[field];
-      }
-
-      // Format wanted fields
-      for (let i = 0, len = contractFields.length; i < len; i++) {
-        let prop = contractFields[i];
-        let propType = contract[prop];
-        let t = "";
-        if (propType.name) {
-          t = propType.name;
-        } else if (propType.length != undefined) {
-          t = 'Array';
-        } else {
-          t = 'Object';
-        }
-        // Test json member type
-        let tjson = typeof json[prop];
-        if (~['Array', 'Object'].indexOf(t)) {
-          if (tjson == 'object' && json[prop] !== null) {
-            tjson = json[prop].length == undefined ? 'Object' : 'Array';
-          }
-        }
-        // Check coherence & alter member if needed
-        if (!_(json[prop]).isNull() && t.toLowerCase() != tjson.toLowerCase()) {
-          try {
-            if (t == "String") {
-              let s = json[prop] == undefined ? '' : json[prop];
-              json[prop] = String(s).valueOf();
-            }
-            else if (t == "Number") {
-              let s = json[prop] == undefined ? '' : json[prop];
-              json[prop] = Number(s).valueOf();
-            }
-            else if (t == "Array") {
-              json[prop] = [];
-            }
-            else if (t == "Object") {
-              json[prop] = {};
-            }
-            else {
-              json[prop] = Boolean();
-            }
-          } catch (ex) {
-            if (t == "String") {
-              json[prop] = String();
-            }
-            else if (t == "Number") {
-              json[prop] = Number();
-            }
-            else if (t == "Array") {
-              json[prop] = [];
-            }
-            else if (t == "Object") {
-              json[prop] = {};
-            }
-            else {
-              json[prop] = Boolean();
-            }
-          }
-        }
-        // Arrays
-        if (t == 'Array') {
-          let subt = propType[0];
-          for (let j = 0, len2 = json[prop].length; j < len2; j++) {
-            if (!(subt == "String" || subt == "Number")) {
-              json[prop][j] = sanitize(json[prop][j], subt);
-            }
-          }
-        }
-        // Recursivity
-        if (t == 'Object' && json[prop] !== null) {
-          json[prop] = sanitize(json[prop], contract[prop]);
-        }
-      }
-    }
-  }
-  return json;
-};
diff --git a/app/lib/system/limiter.js b/app/lib/system/limiter.js
deleted file mode 100644
index 6fe411e35..000000000
--- a/app/lib/system/limiter.js
+++ /dev/null
@@ -1,114 +0,0 @@
-"use strict";
-
-const A_MINUTE = 60 * 1000;
-const A_SECOND = 1000;
-
-const Limiter = {
-
-  /**
-   * Tells wether the quota is reached at current time or not.
-   */
-  canAnswerNow() {
-    // Rapid decision first.
-    // Note: we suppose limitPerSecond < limitPerMinute
-    if (this.reqsSecLen < this.limitPerSecond && this.reqsMinLen < this.limitPerMinute) {
-      return true;
-    }
-    this.updateRequests();
-    return this.reqsSecLen < this.limitPerSecond && this.reqsMinLen < this.limitPerMinute;
-  },
-
-  /**
-   * Filter the current requests stock to remove the too old ones
-   */
-  updateRequests() {
-    // Clean current requests stock and make the test again
-    const now = Date.now();
-    let i = 0, reqs = this.reqsMin, len = this.reqsMinLen;
-    // Reinit specific indicators
-    this.reqsSec = [];
-    this.reqsMin = [];
-    while (i < len) {
-      const duration = now - reqs[i];
-      if (duration < A_SECOND) {
-        this.reqsSec.push(reqs[i]);
-      }
-      if (duration < A_MINUTE) {
-        this.reqsMin.push(reqs[i]);
-      }
-      i++;
-    }
-    this.reqsSecLen = this.reqsSec.length;
-    this.reqsMinLen = this.reqsMin.length;
-  },
-  
-  processRequest() {
-    const now = Date.now();
-    this.reqsSec.push(now);
-    this.reqsSecLen++;
-    this.reqsMin.push(now);
-    this.reqsMinLen++;
-  }
-};
-
-let HIGH_USAGE_STRATEGY = Object.create(Limiter);
-HIGH_USAGE_STRATEGY.limitPerSecond = 10;
-HIGH_USAGE_STRATEGY.limitPerMinute = 300;
-
-let VERY_HIGH_USAGE_STRATEGY = Object.create(Limiter);
-VERY_HIGH_USAGE_STRATEGY.limitPerSecond = 30;
-VERY_HIGH_USAGE_STRATEGY.limitPerMinute = 30 * 60; // Limit is only per second
-
-let TEST_STRATEGY = Object.create(Limiter);
-TEST_STRATEGY.limitPerSecond = 5;
-TEST_STRATEGY.limitPerMinute = 6;
-
-let NO_LIMIT_STRATEGY = Object.create(Limiter);
-NO_LIMIT_STRATEGY.limitPerSecond = 1000000;
-NO_LIMIT_STRATEGY.limitPerMinute = 1000000 * 60;
-
-let disableLimits = false;
-
-module.exports = {
-  
-  limitAsHighUsage() {
-    return disableLimits ? createObject(NO_LIMIT_STRATEGY) : createObject(HIGH_USAGE_STRATEGY);
-  },
-
-  limitAsVeryHighUsage() {
-    return disableLimits ? createObject(NO_LIMIT_STRATEGY) : createObject(VERY_HIGH_USAGE_STRATEGY);
-  },
-
-  limitAsUnlimited() {
-    return createObject(NO_LIMIT_STRATEGY);
-  },
-
-  limitAsTest() {
-    return disableLimits ? createObject(NO_LIMIT_STRATEGY) : createObject(TEST_STRATEGY);
-  },
-
-  noLimit() {
-    disableLimits = true;
-  },
-
-  withLimit() {
-    disableLimits = false;
-  }
-};
-
-function createObject(strategy) {
-
-  const obj = Object.create(strategy);
-
-  // Stock of request times
-  obj.reqsSec = [];
-
-    // The length of reqs.
-    // It is better to have it instead of calling reqs.length
-  obj.reqsSecLen = 0;
-
-    // Minute specific
-  obj.reqsMin = [];
-  obj.reqsMinLen = 0;
-  return obj;
-}
diff --git a/app/lib/system/network.js b/app/lib/system/network.js
index a11a911e7..b14be0f28 100644
--- a/app/lib/system/network.js
+++ b/app/lib/system/network.js
@@ -2,29 +2,16 @@
 
 const co = require('co');
 const os = require('os');
-const Q = require('q');
 const _ = require('underscore');
-const ddos = require('ddos');
-const http = require('http');
-const express = require('express');
-const morgan = require('morgan');
-const errorhandler = require('errorhandler');
-const bodyParser = require('body-parser');
-const cors = require('cors');
-const fileUpload = require('express-fileupload');
-const constants = require('../constants');
-const sanitize = require('../streams/sanitize');
 const logger = require('../logger')('network');
 
-const bmapiMethods = require('../../modules/bmapi').duniter.methods;
+const bmapiMethods = require('duniter-bma').duniter.methods;
 
 module.exports = {
 
   getEndpoint: getEndpoint,
   getBestLocalIPv4: bmapiMethods.getBestLocalIPv4,
   getBestLocalIPv6: bmapiMethods.getBestLocalIPv6,
-  getLANIPv4: () => getLAN('IPv4'),
-  getLANIPv6: () => getLAN('IPv6'),
 
   listInterfaces: bmapiMethods.listInterfaces,
 
@@ -32,225 +19,9 @@ module.exports = {
 
   getRandomPort: bmapiMethods.getRandomPort,
 
-  createServersAndListen: (name, interfaces, httpLogs, staticPath, routingCallback, listenWebSocket, enableFileUpload) => co(function *() {
-
-    const app = express();
-
-    // all environments
-    if (httpLogs) {
-      app.use(morgan('\x1b[90m:remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms\x1b[0m', {
-        stream: {
-          write: function(message){
-            message && logger.trace(message.replace(/\n$/,''));
-          }
-        }
-      }));
-    }
-
-    // DDOS protection
-    const whitelist = interfaces.map(i => i.ip);
-    if (whitelist.indexOf('127.0.0.1') === -1) {
-      whitelist.push('127.0.0.1');
-    }
-    const ddosInstance = new ddos({ whitelist, silentStart: true });
-    app.use(ddosInstance.express);
-
-    // CORS for **any** HTTP request
-    app.use(cors());
-
-    if (enableFileUpload) {
-      // File upload for backup API
-      app.use(fileUpload());
-    }
-
-    app.use(bodyParser.urlencoded({
-      extended: true
-    }));
-    app.use(bodyParser.json());
-
-    // development only
-    if (app.get('env') == 'development') {
-      app.use(errorhandler());
-    }
-
-    routingCallback(app, {
-      httpGET:     (uri, promiseFunc, dtoContract, limiter) => handleRequest(app.get.bind(app), uri, promiseFunc, dtoContract, limiter),
-      httpPOST:    (uri, promiseFunc, dtoContract, limiter) => handleRequest(app.post.bind(app), uri, promiseFunc, dtoContract, limiter),
-      httpGETFile: (uri, promiseFunc, dtoContract, limiter) => handleFileRequest(app.get.bind(app), uri, promiseFunc, limiter)
-    });
-
-    if (staticPath) {
-      app.use(express.static(staticPath));
-    }
-
-    const httpServers = interfaces.map(() => {
-      const httpServer = http.createServer(app);
-      const sockets = {};
-      let nextSocketId = 0;
-      httpServer.on('connection', (socket) => {
-        const socketId = nextSocketId++;
-        sockets[socketId] = socket;
-        //logger.debug('socket %s opened', socketId);
-
-        socket.on('close', () => {
-          //logger.debug('socket %s closed', socketId);
-          delete sockets[socketId];
-        });
-      });
-      httpServer.on('error', (err) => {
-        httpServer.errorPropagates(err);
-      });
-      listenWebSocket && listenWebSocket(httpServer);
-      return {
-        http: httpServer,
-        closeSockets: () => {
-          _.keys(sockets).map((socketId) => {
-            sockets[socketId].destroy();
-          });
-        }
-      };
-    });
-
-    // May be removed when using Node 5.x where httpServer.listening boolean exists
-    const listenings = interfaces.map(() => false);
-
-    if (httpServers.length == 0){
-      throw 'Duniter does not have any interface to listen to.';
-    }
-
-    // Return API
-    return {
-
-      getDDOS: () => ddosInstance,
-
-      closeConnections: () => co(function *() {
-        for (let i = 0, len = httpServers.length; i < len; i++) {
-          const httpServer = httpServers[i].http;
-          const isListening = listenings[i];
-          if (isListening) {
-            listenings[i] = false;
-            logger.info(name + ' stop listening');
-            yield Q.Promise((resolve, reject) => {
-              httpServer.errorPropagates((err) => {
-                reject(err);
-              });
-              httpServers[i].closeSockets();
-              httpServer.close((err) => {
-                err && logger.error(err.stack || err);
-                resolve();
-              });
-            });
-          }
-        }
-        return [];
-      }),
-
-      openConnections: () => co(function *() {
-        for (let i = 0, len = httpServers.length; i < len; i++) {
-          const httpServer = httpServers[i].http;
-          const isListening = listenings[i];
-          if (!isListening) {
-            const netInterface = interfaces[i].ip;
-            const port = interfaces[i].port;
-            try {
-              yield Q.Promise((resolve, reject) => {
-                // Weird the need of such a hack to catch an exception...
-                httpServer.errorPropagates = function(err) {
-                  reject(err);
-                };
-                //httpServer.on('listening', resolve.bind(this, httpServer));
-                httpServer.listen(port, netInterface, (err) => {
-                  if (err) return reject(err);
-                  listenings[i] = true;
-                  resolve(httpServer);
-                });
-              });
-              logger.info(name + ' listening on http://' + (netInterface.match(/:/) ? '[' + netInterface + ']' : netInterface) + ':' + port);
-            } catch (e) {
-              logger.warn('Could NOT listen to http://' + netInterface + ':' + port);
-              logger.warn(e);
-            }
-          }
-        }
-        return [];
-      })
-    };
-  })
-};
-
-const handleRequest = (method, uri, promiseFunc, dtoContract, theLimiter) => {
-  const limiter = theLimiter || require('../system/limiter').limitAsUnlimited();
-  method(uri, function(req, res) {
-    res.set('Access-Control-Allow-Origin', '*');
-    res.type('application/json');
-    co(function *() {
-      try {
-        if (!limiter.canAnswerNow()) {
-          throw constants.ERRORS.HTTP_LIMITATION;
-        }
-        limiter.processRequest();
-        let result = yield promiseFunc(req);
-        // Ensure of the answer format
-        result = sanitize(result, dtoContract);
-        // HTTP answer
-        res.status(200).send(JSON.stringify(result, null, "  "));
-      } catch (e) {
-        let error = getResultingError(e);
-        // HTTP error
-        res.status(error.httpCode).send(JSON.stringify(error.uerr, null, "  "));
-      }
-    });
-  });
-};
-
-const handleFileRequest = (method, uri, promiseFunc, theLimiter) => {
-  const limiter = theLimiter || require('../system/limiter').limitAsUnlimited();
-  method(uri, function(req, res) {
-    res.set('Access-Control-Allow-Origin', '*');
-    co(function *() {
-      try {
-        if (!limiter.canAnswerNow()) {
-          throw constants.ERRORS.HTTP_LIMITATION;
-        }
-        limiter.processRequest();
-        let fileStream = yield promiseFunc(req);
-        // HTTP answer
-        fileStream.pipe(res);
-      } catch (e) {
-        let error = getResultingError(e);
-        // HTTP error
-        res.status(error.httpCode).send(JSON.stringify(error.uerr, null, "  "));
-        throw e
-      }
-    });
-  });
+  createServersAndListen: require('duniter-bma').duniter.methods.createServersAndListen
 };
 
-function getResultingError(e) {
-  // Default is 500 unknown error
-  let error = constants.ERRORS.UNKNOWN;
-  if (e) {
-    // Print eventual stack trace
-    typeof e == 'string' && logger.error(e);
-    e.stack && logger.error(e.stack);
-    e.message && logger.warn(e.message);
-    // BusinessException
-    if (e.uerr) {
-      error = e;
-    } else {
-      const cp = constants.ERRORS.UNHANDLED;
-      error = {
-        httpCode: cp.httpCode,
-        uerr: {
-          ucode: cp.uerr.ucode,
-          message: e.message || e || error.uerr.message
-        }
-      };
-    }
-  }
-  return error;
-}
-
 function getEndpoint(theConf) {
   let endpoint = 'BASIC_MERKLED_API';
   if (theConf.remotehost) {
@@ -267,25 +38,3 @@ function getEndpoint(theConf) {
   }
   return endpoint;
 }
-
-function getLAN(family) {
-  let netInterfaces = os.networkInterfaces();
-  let keys = _.keys(netInterfaces);
-  let res = [];
-  for (const name of keys) {
-    let addresses = netInterfaces[name];
-    for (const addr of addresses) {
-      if ((addr.family == "IPv4" && family == "IPv4"
-          && addr.address != "127.0.0.1" && addr.address != "lo" && addr.address != "localhost")
-          || (addr.family == "IPv6" && family == "IPv6"
-          && addr.address != "::1" && addr.address != "lo" && addr.address != "localhost"))
-      {
-        res.push({
-          name: name,
-          value: addr.address
-        });
-      }
-    }
-  }
-  return res;
-}
diff --git a/app/lib/system/upnp.js b/app/lib/system/upnp.js
deleted file mode 100644
index fda7375ee..000000000
--- a/app/lib/system/upnp.js
+++ /dev/null
@@ -1,66 +0,0 @@
-const upnp = require('nnupnp');
-const async = require('async');
-const constants  = require('../constants');
-const logger = require('../logger')('upnp');
-const co = require('co');
-const Q = require('q');
-
-module.exports = function (localPort, remotePort) {
-  "use strict";
-  return co(function *() {
-    logger.info('UPnP: configuring...');
-    return co(function *() {
-      try {
-        yield openPort(localPort, remotePort);
-      } catch (e) {
-        const client = upnp.createClient();
-        try {
-          yield Q.nbind(client.externalIp, client)();
-        } catch (err) {
-          if (err && err.message == 'timeout') {
-            throw 'No UPnP gateway found: your node won\'t be reachable from the Internet. Use --noupnp option to avoid this message.'
-          }
-          throw err;
-        } finally {
-          client.close();
-        }
-      }
-      let interval, upnpService = {
-        openPort: () => {
-          return openPort(localPort, remotePort);
-        },
-        startRegular: () => {
-          upnpService.stopRegular();
-          // Update UPnP IGD every INTERVAL seconds
-          interval = setInterval(async.apply(openPort, localPort, remotePort), 1000 * constants.NETWORK.UPNP.INTERVAL);
-        },
-        stopRegular: () => {
-          if (interval) {
-            clearInterval(interval);
-          }
-        }
-      };
-      return upnpService;
-    });
-  });
-};
-
-function openPort (localPort, remotePort) {
-  "use strict";
-  return Q.Promise(function(resolve, reject){
-    logger.trace('UPnP: mapping external port %s to local %s...', remotePort, localPort);
-    const client = upnp.createClient();
-    client.portMapping({
-      'public': parseInt(remotePort),
-      'private': parseInt(localPort),
-      'ttl': constants.NETWORK.UPNP.TTL
-    }, function(err) {
-      client.close();
-      if (err) {
-        logger.warn(err);
-        return reject(err);
-      }
-      resolve();
-    });
-  });
-}
diff --git a/app/modules/bmapi.js b/app/modules/bmapi.js
deleted file mode 100644
index f245b4e4e..000000000
--- a/app/modules/bmapi.js
+++ /dev/null
@@ -1,564 +0,0 @@
-"use strict";
-
-const Q = require('q');
-const co = require('co');
-const os = require('os');
-const async = require('async');
-const _ = require('underscore');
-const util = require('util');
-const stream = require('stream');
-const constants = require('../lib/constants');
-const upnp = require('../lib/system/upnp');
-const inquirer = require('inquirer');
-
-module.exports = {
-  duniter: {
-
-    cliOptions: [
-      { value: '--upnp', desc: 'Use UPnP to open remote port.' },
-      { value: '--noupnp', desc: 'Do not use UPnP to open remote port.' }
-    ],
-
-    wizard: {
-
-      'network': (conf, program, logger) => co(function*() {
-        yield Q.nbind(networkConfiguration, null, conf, logger)();
-      }),
-
-      'network-reconfigure': (conf, program, logger) => co(function*() {
-        yield Q.nbind(networkReconfiguration, null, conf, logger, program.autoconf, program.noupnp)();
-      })
-    },
-
-    config: {
-
-      onLoading: (conf, program, logger) => co(function*(){
-
-        // Network autoconf
-        const autoconfNet = program.autoconf
-          || !(conf.ipv4 || conf.ipv6)
-          || !(conf.remoteipv4 || conf.remoteipv6 || conf.remotehost)
-          || !(conf.port && conf.remoteport);
-        if (autoconfNet) {
-          yield Q.nbind(networkReconfiguration, null)(conf, autoconfNet, logger, program.noupnp);
-        }
-
-        // Default value
-        if (conf.upnp === undefined || conf.upnp === null) {
-          conf.upnp = true; // Defaults to true
-        }
-
-        // UPnP
-        if (program.noupnp === true) {
-          conf.upnp = false;
-        }
-        if (program.upnp === true) {
-          conf.upnp = true;
-        }
-      })
-    },
-
-    service: {
-      input: (server, conf, logger) => new BMAPI(server, conf, logger)
-    },
-
-    methods: {
-      upnpConf, listInterfaces, getBestLocalIPv4, getBestLocalIPv6, getRandomPort
-    }
-  }
-}
-
-function BMAPI(server, conf, logger) {
-
-  // Public http interface
-  let bmapi;
-  // UPnP API
-  let upnpAPI;
-
-  stream.Transform.call(this, { objectMode: true });
-
-  this.startService = () => co(function*() {
-    const bma = require('../lib/streams/bma');
-    bmapi = yield bma(server, null, conf.httplogs);
-    yield bmapi.openConnections();
-
-    /***************
-     *    UPnP
-     **************/
-    if (upnpAPI) {
-      upnpAPI.stopRegular();
-    }
-    if (conf.upnp) {
-      try {
-        upnpAPI = yield upnp(conf.port, conf.remoteport);
-        upnpAPI.startRegular();
-      } catch (e) {
-        logger.warn(e);
-      }
-    }
-  });
-
-  this.stopService = () => co(function*() {
-    if (bmapi) {
-      yield bmapi.closeConnections();
-    }
-    if (upnpAPI) {
-      upnpAPI.stopRegular();
-    }
-  });
-}
-
-
-
-function networkReconfiguration(conf, autoconf, logger, noupnp, done) {
-  async.waterfall([
-    upnpResolve.bind(this, noupnp, logger),
-    function(upnpSuccess, upnpConf, next) {
-
-      // Default values
-      conf.port = conf.port || constants.NETWORK.DEFAULT_PORT;
-      conf.remoteport = conf.remoteport || constants.NETWORK.DEFAULT_PORT;
-
-      var localOperations = getLocalNetworkOperations(conf, autoconf);
-      var remoteOpertions = getRemoteNetworkOperations(conf, upnpConf.remoteipv4, upnpConf.remoteipv6, autoconf);
-      var dnsOperations = getHostnameOperations(conf, logger, autoconf);
-      var useUPnPOperations = getUseUPnPOperations(conf, logger, autoconf);
-
-      if (upnpSuccess) {
-        _.extend(conf, upnpConf);
-        var local = [conf.ipv4, conf.port].join(':');
-        var remote = [conf.remoteipv4, conf.remoteport].join(':');
-        if (autoconf) {
-          conf.ipv6 = conf.remoteipv6 = getBestLocalIPv6();
-          logger.info('IPv6: %s', conf.ipv6 || "");
-          logger.info('Local IPv4: %s', local);
-          logger.info('Remote IPv4: %s', remote);
-          // Use proposed local + remote with UPnP binding
-          return async.waterfall(useUPnPOperations
-            .concat(dnsOperations), next);
-        }
-        choose("UPnP is available: duniter will be bound: \n  from " + local + "\n  to " + remote + "\nKeep this configuration?", true,
-          function () {
-            // Yes: not network changes
-            conf.ipv6 = conf.remoteipv6 = getBestLocalIPv6();
-            async.waterfall(useUPnPOperations
-              .concat(dnsOperations), next);
-          },
-          function () {
-            // No: want to change
-            async.waterfall(
-              localOperations
-                .concat(remoteOpertions)
-                .concat(useUPnPOperations)
-                .concat(dnsOperations), next);
-          });
-      } else {
-        conf.upnp = false;
-        if (autoconf) {
-          // Yes: local configuration = remote configuration
-          return async.waterfall(
-            localOperations
-              .concat(getHostnameOperations(conf, logger, autoconf))
-              .concat([function (confDone) {
-                conf.remoteipv4 = conf.ipv4;
-                conf.remoteipv6 = conf.ipv6;
-                conf.remoteport = conf.port;
-                logger.info('Local & Remote IPv4: %s', [conf.ipv4, conf.port].join(':'));
-                logger.info('Local & Remote IPv6: %s', [conf.ipv6, conf.port].join(':'));
-                confDone();
-              }]), next);
-        }
-        choose("UPnP is *not* available: is this a public server (like a VPS)?", true,
-          function () {
-            // Yes: local configuration = remote configuration
-            async.waterfall(
-              localOperations
-                .concat(getHostnameOperations(conf, logger))
-                .concat([function(confDone) {
-                  conf.remoteipv4 = conf.ipv4;
-                  conf.remoteipv6 = conf.ipv6;
-                  conf.remoteport = conf.port;
-                  confDone();
-                }]), next);
-          },
-          function () {
-            // No: must give all details
-            async.waterfall(
-              localOperations
-                .concat(remoteOpertions)
-                .concat(dnsOperations), next);
-          });
-      }
-    }
-  ], done);
-}
-
-
-function upnpResolve(noupnp, logger, done) {
-  return co(function *() {
-    try {
-      let conf = yield upnpConf(noupnp, logger);
-      done(null, true, conf);
-    } catch (err) {
-      done(null, false, {});
-    }
-  });
-}
-
-function networkConfiguration(conf, logger, done) {
-  async.waterfall([
-    upnpResolve.bind(this, !conf.upnp, logger),
-    function(upnpSuccess, upnpConf, next) {
-
-      var operations = getLocalNetworkOperations(conf)
-        .concat(getRemoteNetworkOperations(conf, upnpConf.remoteipv4, upnpConf.remoteipv6));
-
-      if (upnpSuccess) {
-        operations = operations.concat(getUseUPnPOperations(conf, logger));
-      }
-
-      async.waterfall(operations.concat(getHostnameOperations(conf, logger, false)), next);
-    }
-  ], done);
-}
-
-function getLocalNetworkOperations(conf, autoconf) {
-  return [
-    function (next){
-      var osInterfaces = listInterfaces();
-      var interfaces = [{ name: "None", value: null }];
-      osInterfaces.forEach(function(netInterface){
-        var addresses = netInterface.addresses;
-        var filtered = _(addresses).where({family: 'IPv4'});
-        filtered.forEach(function(addr){
-          interfaces.push({
-            name: [netInterface.name, addr.address].join(' '),
-            value: addr.address
-          });
-        });
-      });
-      if (autoconf) {
-        conf.ipv4 = getBestLocalIPv4();
-        return next();
-      }
-      inquirer.prompt([{
-        type: "list",
-        name: "ipv4",
-        message: "IPv4 interface",
-        default: conf.ipv4,
-        choices: interfaces
-      }], function (answers) {
-        conf.ipv4 = answers.ipv4;
-        next();
-      });
-    },
-    function (next){
-      var osInterfaces = listInterfaces();
-      var interfaces = [{ name: "None", value: null }];
-      osInterfaces.forEach(function(netInterface){
-        var addresses = netInterface.addresses;
-        var filtered = _(addresses).where({ family: 'IPv6' });
-        filtered.forEach(function(addr){
-          var address = addr.address
-          if (addr.scopeid)
-            address += "%" + netInterface.name
-          let nameSuffix = "";
-          if (addr.scopeid == 0 && !addr.internal) {
-            nameSuffix = " (Global)";
-          }
-          interfaces.push({
-            name: [netInterface.name, address, nameSuffix].join(' '),
-            internal: addr.internal,
-            scopeid: addr.scopeid,
-            value: address
-          });
-        });
-      });
-      interfaces.sort((addr1, addr2) => {
-        if (addr1.value === null) return -1;
-        if (addr1.internal && !addr2.internal) return 1;
-        if (addr1.scopeid && !addr2.scopeid) return 1;
-        return 0;
-      });
-      if (autoconf || !conf.ipv6) {
-        conf.ipv6 = conf.remoteipv6 = getBestLocalIPv6();
-      }
-      if (autoconf) {
-        return next();
-      }
-      inquirer.prompt([{
-        type: "list",
-        name: "ipv6",
-        message: "IPv6 interface",
-        default: conf.ipv6,
-        choices: interfaces
-      }], function (answers) {
-        conf.ipv6 = conf.remoteipv6 = answers.ipv6;
-        next();
-      });
-    },
-    autoconf ? (done) => {
-        conf.port = getRandomPort(conf);
-        done();
-      } : async.apply(simpleInteger, "Port", "port", conf)
-  ];
-}
-
-function getRemoteNetworkOperations(conf, remoteipv4) {
-  return [
-    function (next){
-      if (!conf.ipv4) {
-        conf.remoteipv4 = null;
-        return next(null, {});
-      }
-      var choices = [{ name: "None", value: null }];
-      // Local interfaces
-      var osInterfaces = listInterfaces();
-      osInterfaces.forEach(function(netInterface){
-        var addresses = netInterface.addresses;
-        var filtered = _(addresses).where({family: 'IPv4'});
-        filtered.forEach(function(addr){
-          choices.push({
-            name: [netInterface.name, addr.address].join(' '),
-            value: addr.address
-          });
-        });
-      });
-      if (conf.remoteipv4) {
-        choices.push({ name: conf.remoteipv4, value: conf.remoteipv4 });
-      }
-      if (remoteipv4 && remoteipv4 != conf.remoteipv4) {
-        choices.push({ name: remoteipv4, value: remoteipv4 });
-      }
-      choices.push({ name: "Enter new one", value: "new" });
-      inquirer.prompt([{
-        type: "list",
-        name: "remoteipv4",
-        message: "Remote IPv4",
-        default: conf.remoteipv4 || conf.ipv4 || null,
-        choices: choices,
-        validate: function (input) {
-          return input && input.toString().match(constants.IPV4_REGEXP) ? true : false;
-        }
-      }], function (answers) {
-        if (answers.remoteipv4 == "new") {
-          inquirer.prompt([{
-            type: "input",
-            name: "remoteipv4",
-            message: "Remote IPv4",
-            default: conf.remoteipv4 || conf.ipv4,
-            validate: function (input) {
-              return input && input.toString().match(constants.IPV4_REGEXP) ? true : false;
-            }
-          }], async.apply(next, null));
-        } else {
-          next(null, answers);
-        }
-      });
-    },
-    function (answers, next){
-      conf.remoteipv4 = answers.remoteipv4;
-      return co(function*() {
-        try {
-          if (conf.remoteipv4 || conf.remotehost) {
-            yield new Promise((resolve, reject) => {
-              const getPort = async.apply(simpleInteger, "Remote port", "remoteport", conf);
-              getPort((err) => {
-                if (err) return reject(err);
-                resolve();
-              });
-            });
-          } else if (conf.remoteipv6) {
-            conf.remoteport = conf.port;
-          }
-          next();
-        } catch (e) {
-          next(e);
-        }
-      });
-    }
-  ];
-}
-
-function getHostnameOperations(conf, logger, autoconf) {
-  return [function(next) {
-    if (!conf.ipv4) {
-      conf.remotehost = null;
-      return next();
-    }
-    if (autoconf) {
-      logger.info('DNS: %s', conf.remotehost || 'No');
-      return next();
-    }
-    choose("Does this server has a DNS name?", !!conf.remotehost,
-      function() {
-        // Yes
-        simpleValue("DNS name:", "remotehost", "", conf, function(){ return true; }, next);
-      },
-      function() {
-        conf.remotehost = null;
-        next();
-      });
-  }];
-}
-
-function getUseUPnPOperations(conf, logger, autoconf) {
-  return [function(next) {
-    if (!conf.ipv4) {
-      conf.upnp = false;
-      return next();
-    }
-    if (autoconf) {
-      logger.info('UPnP: %s', 'Yes');
-      conf.upnp = true;
-      return next();
-    }
-    choose("UPnP is available: use automatic port mapping? (easier)", conf.upnp,
-      function() {
-        conf.upnp = true;
-        next();
-      },
-      function() {
-        conf.upnp = false;
-        next();
-      });
-  }];
-}
-
-function choose (question, defaultValue, ifOK, ifNotOK) {
-  inquirer.prompt([{
-    type: "confirm",
-    name: "q",
-    message: question,
-    default: defaultValue
-  }], function (answer) {
-    answer.q ? ifOK() : ifNotOK();
-  });
-}
-
-function upnpConf (noupnp, logger) {
-  return co(function *() {
-    const conf = {};
-    const client = require('nnupnp').createClient();
-    // Look for 2 random ports
-    const privatePort = getRandomPort(conf);
-    const publicPort = privatePort;
-    logger.info('Checking UPnP features...');
-    if (noupnp) {
-      throw Error('No UPnP');
-    }
-    const publicIP = yield Q.nbind(client.externalIp, client)();
-    yield Q.nbind(client.portMapping, client)({
-      public: publicPort,
-      private: privatePort,
-      ttl: 120
-    });
-    const privateIP = yield Q.Promise((resolve, reject) => {
-      client.findGateway((err, res, localIP) => {
-        if (err) return reject(err);
-        resolve(localIP);
-      });
-    });
-    conf.remoteipv4 = publicIP.match(constants.IPV4_REGEXP) ? publicIP : null;
-    conf.remoteport = publicPort;
-    conf.port = privatePort;
-    conf.ipv4 = privateIP.match(constants.IPV4_REGEXP) ? privateIP : null;
-    return conf;
-  });
-}
-
-function simpleValue (question, property, defaultValue, conf, validation, done) {
-  inquirer.prompt([{
-    type: "input",
-    name: property,
-    message: question,
-    default: conf[property],
-    validate: validation
-  }], function (answers) {
-    conf[property] = answers[property];
-    done();
-  });
-}
-
-function simpleInteger (question, property, conf, done) {
-  simpleValue(question, property, conf[property], conf, function (input) {
-    return input && input.toString().match(/^[0-9]+$/) ? true : false;
-  }, done);
-}
-
-function listInterfaces() {
-  const netInterfaces = os.networkInterfaces();
-  const keys = _.keys(netInterfaces);
-  const res = [];
-  for (const name of keys) {
-    res.push({
-      name: name,
-      addresses: netInterfaces[name]
-    });
-  }
-  return res;
-}
-
-function getBestLocalIPv4() {
-  return getBestLocal('IPv4');
-}
-
-function getBestLocalIPv6() {
-  const osInterfaces = listInterfaces();
-  for (let netInterface of osInterfaces) {
-    const addresses = netInterface.addresses;
-    const filtered = _(addresses).where({family: 'IPv6', scopeid: 0, internal: false });
-    const filtered2 = _(filtered).filter((address) => !address.address.match(/^fe80/) && !address.address.match(/^::1/));
-    if (filtered2[0]) {
-      return filtered2[0].address;
-    }
-  }
-  return null;
-}
-
-function getBestLocal(family) {
-  let netInterfaces = os.networkInterfaces();
-  let keys = _.keys(netInterfaces);
-  let res = [];
-  for (const name of keys) {
-    let addresses = netInterfaces[name];
-    for (const addr of addresses) {
-      if (!family || addr.family == family) {
-        res.push({
-          name: name,
-          value: addr.address
-        });
-      }
-    }
-  }
-  const interfacePriorityRegCatcher = [
-    /^tun\d/,
-    /^enp\ds\d/,
-    /^enp\ds\df\d/,
-    /^eth\d/,
-    /^Ethernet/,
-    /^wlp\ds\d/,
-    /^wlan\d/,
-    /^Wi-Fi/,
-    /^lo/,
-    /^Loopback/,
-    /^None/
-  ];
-  const best = _.sortBy(res, function(entry) {
-    for(let priority in interfacePriorityRegCatcher){
-      if (entry.name.match(interfacePriorityRegCatcher[priority])) return priority;
-    }
-    return interfacePriorityRegCatcher.length;
-  })[0];
-  return (best && best.value) || "";
-}
-
-function getRandomPort(conf) {
-  if (conf && conf.remoteport) {
-    return conf.remoteport;
-  } else {
-    return ~~(Math.random() * (65536 - constants.NETWORK.PORT.START)) + constants.NETWORK.PORT.START;
-  }
-}
-
-util.inherits(BMAPI, stream.Transform);
diff --git a/doc/HTTP_API.md b/doc/HTTP_API.md
deleted file mode 100644
index 6cd7f026c..000000000
--- a/doc/HTTP_API.md
+++ /dev/null
@@ -1,1812 +0,0 @@
-# Duniter HTTP API
-
-## Contents
-
-* [Contents](#contents)
-* [Overview](#overview)
-* [Merkle URLs](#merkle-urls)
-* [API](#api)
-  * [node/](#node)
-      * [summary](#nodesummary)
-  * [wot/](#wot)
-      * [add](#wotadd)
-      * [certify](#wotcertify)
-      * [revoke](#wotrevoke)
-      * [lookup/[search]](#wotlookupsearch)
-      * [requirements/[PUBKEY]](#wotrequirementspubkey)
-      * [certifiers-of/[search]](#wotcertifiers-ofsearch)
-      * [certified-by/[search]](#wotcertified-bysearch)
-  * [blockchain/](#blockchain)
-      * [parameters](#blockchainparameters)
-      * [membership](#blockchainmembership)
-      * [memberships/[search]](#blockchainmembershipssearch)
-      * [block](#blockchainblock)
-      * [block/[number]](#blockchainblocknumber)
-      * [blocks/[count]/[from]](#blockchainblockscountfrom)
-      * [current](#blockchaincurrent)
-      * [hardship/[PUBKEY]](#blockchainhardshippubkey)
-      * [difficulties](#blockchaindifficulties)
-      * [with/](#blockchainwith)
-          * [newcomers](#blockchainwithnewcomers)
-          * [certs](#blockchainwithcerts)
-          * [actives](#blockchainwithactives)
-          * [leavers](#blockchainwithleavers)
-          * [excluded](#blockchainwithexcluded)
-          * [ud](#blockchainwithud)
-          * [tx](#blockchainwithtx)
-      * [branches](#blockchainbranches)
-  * [network/](#network)
-      * [peers](#networkpeers)
-      * [peering](#networkpeering)
-      * [peering/peers (GET)](#networkpeeringpeers-get)
-      * [peering/peers (POST)](#networkpeeringpeers-post)
-  * [tx/](#tx)
-      * [process](#txprocess)
-      * [sources/[pubkey]](#txsourcespubkey)
-      * [history/[pubkey]](#txhistorypubkey)
-      * [history/[pubkey]/blocks/[from]/[to]](#txhistorypubkeyblocksfromto)
-      * [history/[pubkey]/times/[from]/[to]](#txhistorypubkeytimesfromto)
-  * [ud/](#ud)
-      * [history/[pubkey]](#udhistorypubkey)
-  * [ws/](#ws)
-      * [block](#wsblock)
-      * [peer](#wspeer)
-
-## Overview
-
-Data is made accessible through an HTTP API mainly inspired from [OpenUDC_exchange_formats draft](https://github.com/Open-UDC/open-udc/blob/master/docs/OpenUDC_exchange_formats.draft.txt), and has been adapted to fit Duniter specificities.
-
-    http[s]://Node[:port]/...
-    |-- wot/
-    |   |-- add
-    |   |-- certify
-    |   |-- revoke
-    |   |-- requirements/[pubkey]
-    |   |-- certifiers-of/[uid|pubkey]
-    |   |-- certified-by/[uid|pubkey]
-    |   |-- members
-    |   `-- lookup
-    |-- blockchain/
-    |   |-- parameters
-    |   |-- membership
-    |   |-- with/
-    |       |-- newcomers
-    |       |-- certs
-    |       |-- joiners
-    |       |-- actives
-    |       |-- leavers
-    |       |-- excluded
-    |       |-- ud
-    |       `-- tx
-    |   |-- hardship
-    |   |   `-- [PUBKEY]
-    |   |-- block
-    |   |   `-- [NUMBER]
-    |   |-- difficulties
-    |   `-- current
-    |-- network/
-    |   |-- peers
-    |   `-- peering
-    |       `-- peers
-    |-- tx/
-    |   |-- process
-    |   |-- sources
-    |   `-- history
-    |-- ud/
-    |   `-- history
-    `-- ws/
-        |-- block
-        `-- peer
-
-## Merkle URLs
-
-Merkle URL is a special kind of URL applicable for resources:
-
-* `network/peering/peers (GET)`
-
-Such kind of URL returns Merkle tree hashes informations. In Duniter, Merkle trees are an easy way to detect unsynced data and where the differences come from. For example, `network/peering/peers` is a Merkle tree whose leaves are peers' key fingerprint sorted ascending way. Thus, if any new peer is added, a branch of the tree will see its hash modified and propagated to the root hash. Change is then easy to detect.
-
-For commodity issues, this URL uses query parameters to retrieve partial data of the tree, as most of the time all the data is not required. Duniter Merkle tree has a determined number of parent nodes (given a number of leaves), which allows to ask only for interval of them.
-
-Here is an example of members Merkle tree with 5 members (taken from [Tree Hash EXchange format (THEX)](http://web.archive.org/web/20080316033726/http://www.open-content.net/specs/draft-jchapweske-thex-02.html)):
-
-                       ROOT=H(H+E)
-                        /        \
-                       /          \
-                 H=H(F+G)          E
-                /       \           \
-               /         \           \
-        F=H(A+B)         G=H(C+D)     E
-        /     \           /     \      \
-       /       \         /       \      \
-      A         B       C         D      E
-
-
-    Note: H() is some hash function
-
-Where A,B,C,D,E are already hashed data.
-
-With such a tree structure, Duniter consider the tree has exactly 6 nodes: `[ROOT,H,E,F,G,E]`. Nodes are just an array, and for a Lambda Server LS1, it is easy to ask for the values of another server LS2 for level 1 (`H` and `E`, the second level): it requires nodes interval `[1;2]`.
-
-Hence it is quite easy for anyone who wants to check if a `Z` member joined the Duniter community as it would alter the `E` branch of the tree:
-
-                        ROOT'=H(H+E')
-                        /            \
-                       /              \
-                 H=H(F+G)              E'
-                /       \               \
-               /         \               \
-        F=H(A+B)          G=H(C+D)       E'=H(E+Z)
-        /     \           /     \         /     \
-       /       \         /       \       /       \
-      A         B       C         D     E         Z
-
-`ROOT` changed to `ROOT'`, `E` to `E'`, but `H` did not. The whole `E'` branch should be updated with the proper new data.
-
-For that purpose, Merkle URL defines different parameters and results:
-
-**Parameters**
-
-Parameter | Description
---------- | -----------
-`leaves`  | Defines wether or not leaves hashes should be returned too. Defaults to `false`.
-`leaf`    | Hash of a leaf whose content should be returned. Ignore `leaves` parameter.
-
-**Returns**
-
-Merkle URL result with `leaves=false`.
-```json
-{
-  "depth": 3,
-  "nodesCount": 6,
-  "leavesCount": 5,
-  "root": "6513D6A1582DAE614D8A3B364BF3C64C513D236B"
-}
-```
-
-Merkle URL result with `leaves=true`.
-```json
-{
-  "depth": 3,
-  "nodesCount": 6,
-  "leavesCount": 5,
-  "root": "6513D6A1582DAE614D8A3B364BF3C64C513D236B",
-  "leaves": [
-    "32096C2E0EFF33D844EE6D675407ACE18289357D",
-    "50C9E8D5FC98727B4BBC93CF5D64A68DB647F04F",
-    "6DCD4CE23D88E2EE9568BA546C007C63D9131C1B",
-    "AE4F281DF5A5D0FF3CAD6371F76D5C29B6D953EC",
-    "E0184ADEDF913B076626646D3F52C3B49C39AD6D"
-  ]
-}
-```
-
-Merkle URL result with `leaf=AE4F281DF5A5D0FF3CAD6371F76D5C29B6D953EC`.
-```json
-{
-  "depth": 3,
-  "nodesCount": 6,
-  "leavesCount": 5,
-  "root": "6513D6A1582DAE614D8A3B364BF3C64C513D236B",
-  "leaf": {
-    "hash": "AE4F281DF5A5D0FF3CAD6371F76D5C29B6D953EC",
-    "value": // JSON value (object, string, int, ...)
-  }
-}
-```
-
-### Duniter Merkle trees leaves
-
-Each tree manages different data, and has a different goal. Hence, each tree has its own rules on how are generated and sorted tree leaves.
-Here is a summup of such rules:
-
-
-Merkle URL             | Leaf                      | Sort
----------------------- | --------------------------| -------------
-`network/peers (GET)`    | Hash of the peers' pubkey | By hash string sort, ascending.
-
-#### Unicity
-
-It has to be noted that **possible conflict exists** for leaves, as every leaf is hash, but is rather unlikely.
-
-## API
-
-### node/*
-
-#### `node/summary`
-**Goal**
-
-GET technical informations about this peer.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Technical informations about the node.
-```json
-{
-  "duniter": {
-    "software": "duniter",
-    "version": "0.10.3",
-    "forkWindowSize": 10
-  }
-}
-```
-
-### wot/*
-
-#### `wot/add`
-
-
-**Goal**
-
-POST [Identity](./Protocol.md#identity) data.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`identity` | The raw identity. | POST
-
-**Returns**
-
-The available validated data for this public key.
-```json
-{
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "uids": [
-    {
-      "uid": "udid2;c;TOCQUEVILLE;FRANCOIS-XAVIER-ROBE;1989-07-14;e+48.84+002.30;0;",
-      "meta": {
-        "timestamp": "44-76522E321B3380B058DB6D9E66121705EEA63610869A7C5B3E701CF6AF2D55A8"
-      },
-      "self": "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci",
-      "others": [
-        {
-          "pubkey": "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB",
-          "meta": {
-            "timestamp": "22-2E910FCCCEE008C4B978040CA68211C2395C84C3E6BFB432A267384ED8CD22E5"
-          },
-          "signature": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r"
-        }
-      ]
-    }
-  ]
-}
-```
-
-#### `wot/certify`
-
-
-**Goal**
-
-POST [Certification](./Protocol.md#certification) data.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`cert` | The raw certification. | POST
-
-**Returns**
-
-The available validated data for this public key.
-```json
-{
-  "issuer": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "timestamp": "44-76522E321B3380B058DB6D9E66121705EEA63610869A7C5B3E701CF6AF2D55A8",
-  "sig": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r",
-  "target": {
-    "issuer": "CqwuWfMsPqtUkWdUK6FxV6hPWeHaUfEcz7dFZZJA49BS",
-    "uid": "johnsnow",
-    "timestamp": "44-76522E321B3380B058DB6D9E66121705EEA63610869A7C5B3E701CF6AF2D55A8",
-    "sig": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r",
-  }
-}
-```
-
-#### `wot/revoke`
-
-
-**Goal**
-
-Remove an identity from Identity pool.
-
-> N.B.: An identity **written in the blockchain cannot be removed**.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`revocation` | The raw revocation. | POST
-
-**Returns**
-
-True if operation went well. An HTTP error otherwise with body as error message.
-```json
-{
-  "result": true
-}
-```
-
-#### `wot/lookup/[search]`
-
-
-**Goal**
-
-GET [Public key](./Protocol.md#publickey) data.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`search` | A string of data to look for (public key, uid). | URL
-
-**Returns**
-
-A list of public key data matching search string (may not return all results, check `partial` flag which is set to `false` if all results are here, ` true` otherwise).
-```json
-{
-  "partial": false,
-  "results": [
-    {
-      "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-      "uids": [
-        {
-          "uid": "udid2;c;TOCQUEVILLE;FRANCOIS-XAVIER-ROBE;1989-07-14;e+48.84+002.30;0;",
-          "meta": {
-            "timestamp": "56-97A56CCE04A1B7A03264ADE09545B262CBE65E62DDA481B7D7C89EB4669F5435"
-          },
-          "self": "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci",
-          "revocation_sig": "CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==",
-          "revoked": false,
-          "others": [
-            {
-              "pubkey": "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB",
-              "meta": {
-                "timestamp": "32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD"
-              },
-              "signature": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r"
-            }
-          ]
-        }
-      ],
-      "signed": [
-        {
-          "uid": "snow",
-          "pubkey": "2P7y2UDiCcvsgSSt8sgHF3BPKS4m9waqKw4yXHCuP6CN",
-          "meta": {
-            "timestamp": "33-AB30D958EE5CB75186972286ED3F4686B8A1C2CD"
-          },
-          "revocation_sig": "CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==",
-          "revoked": false,
-          "signature": "Xbr7qhyGNCmLoVuuKnKIbrdmtCvb9VBIEY19izUNwA5nufsjNm8iEsBTwKWOo0lq5O1+AAPMnht8cm2JjMq8AQ=="
-        },
-        {
-          "uid": "snow",
-          "pubkey": "2P7y2UDiCcvsgSSt8sgHF3BPKS4m9waqKw4yXHCuP6CN",
-          "meta": {
-            "timestamp": "978-B38F54242807DFA1A12F17E012D355D8DB92CA6E947FC5D147F131B30C639163"
-          },
-          "revocation_sig": "a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==",
-          "revoked": false,
-          "signature": "HU9VPwC4EqPJwATPuyUJM7HLjfig5Ke1CKonL9Q78n5/uNSL2hkgE9Pxsor8CCJfkwCxh66NjGyqnGYqZnQMAg=="
-        },
-        {
-          "uid": "snow",
-          "pubkey": "7xapQvvxQ6367bs8DsskEf3nvQAgJv97Yu11aPbkCLQj",
-          "meta": {
-            "timestamp": "76-0DC977717C49E69A78A67C6A1526EC17ED380BC68F0C38D290A954471A1349B7"
-          },
-          "revocation_sig": "h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==",
-          "revoked": true,
-          "signature": "6S3x3NwiHB2QqYEY79x4wCUYHcDctbazfxIyxejs38V1uRAl4DuC8R3HJUfD6wMSiWKPqbO+td+8ZMuIn0L8AA=="
-        },
-        {
-          "uid": "cat",
-          "pubkey": "CK2hBp25sYQhdBf9oFMGHyokkmYFfzSCmwio27jYWAN7",
-          "meta": {
-            "timestamp": "63-999677597FC04E6148860AE888A2E1942DF0E1E732C31500BA8EFF07F06FEC0C"
-          },
-          "revocation_sig": "bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==",
-          "revoked": false,
-          "signature": "AhgblSOdxUkLwpUN9Ec46St3JGaw2jPyDn/mLcR4j3EjKxUOwHBYqqkxcQdRz/6K4Qo/xMa941MgUp6NjNbKBA=="
-        }
-      ]
-    }
-  ]
-}
-```
-
-#### `wot/members`
-
-
-**Goal**
-
-GET the list of current Web of Trust members.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-A list of public key + uid.
-```json
-{
-  "results": [
-    { "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY", "uid": "cat" },
-    { "pubkey": "9kNEiyseUNoPn3pmNUhWpvCCwPRgavsLu7YFKZuzzd1L", "uid": "tac" },
-    { "pubkey": "9HJ9VXa9wc6EKC6NkCi8b5TKWBot68VhYDg7kDk5T8Cz", "uid": "toc" }
-  ]
-}
-```
-
-#### `wot/requirements/[pubkey]`
-
-
-**Goal**
-
-GET requirements to be filled by pubkey to become a member.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`pbkey` | Public key to check. | URL
-
-**Returns**
-
-A list of identities matching this pubkey and the requirements of each identities to become a member.
-
-> If the pubkey is matching a member, only one identity may be displayed: the one which is a member.
-
-```json
-{
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "identities": [{
-      "uid": "tobi",
-      "meta": {
-        "timestamp": "12-20504546F37853625C1E695B757D93CFCC6E494069D53F73748E428947933E45"
-      },
-      "outdistanced": true,
-      "certifications": 2,
-      "membershipMissing": true
-    }
-    ...
-  ]
-}
-```
-
-#### `wot/certifiers-of/[search]`
-
-
-**Goal**
-
-GET [Certification](./Protocol.md#certification) data over a member.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`search` | Public key or uid of a *member* (or someone who *was a member*) we want see the certifications. | URL
-
-**Returns**
-
-A list of certifications issued to the member by other members (or who used to be members), with `written` data indicating wether the certification is written in the blockchain or not.
-
-Each certification also has:
-
-* a `isMember` field to indicate wether the issuer of the certification is still a member or not.
-* a `written` field to indicate the block where the certification was written (or null if not written yet).
-
-```json
-{
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "uid": "user identifier",
-  "isMember": true,
-  sigDate: 1421787461,
-  "certifications": [
-    {
-      "pubkey": "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB",
-      "uid": "certifier uid",
-      "cert_time": {
-        "block": 88,
-        "medianTime": 1509991044
-      },
-      sigDate: 1421787461,
-      "written": {
-        "number": 872768,
-        "hash": "D30978C9D6C5A348A8188603F039423D90E50DC5"
-      },
-      "isMember": true,
-      "signature": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r"
-    },
-    ...
-  ]
-}
-```
-
-#### `wot/certified-by/[search]`
-
-
-**Goal**
-
-GET [Certification](./Protocol.md#certification) data over a member.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`search` | Public key or uid of a *member* (or someone who *was a member*) we want see the certifications. | URL
-
-**Returns**
-
-A list of certifications issued by the member to other members (or who used to be members), with `written` data indicating wether the certification is written in the blockchain or not.
-
-Each certification also has:
-
-* a `isMember` field to indicate wether the issuer of the certification is still a member or not.
-* a `written` field to indicate the block where the certification was written (or null if not written yet).
-```json
-{
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "uid": "user identifier",
-  "isMember": true,
-  sigDate: 1421787461,
-  "certifications": [
-    {
-      "pubkey": "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB",
-      "uid": "certifier uid",
-      "cert_time": {
-        "block": 88,
-        "medianTime": 1509991044
-      },
-      sigDate: 1421787461,
-      "written": {
-        "number": 872768,
-        "hash": "D30978C9D6C5A348A8188603F039423D90E50DC5"
-      },
-      "isMember": true,
-      "signature": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r"
-    },
-    ...
-  ]
-}
-```
-
-#### `wot/identity-of/[search]`
-
-
-**Goal**
-
-GET identity data written for a member.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`search` | Public key or uid of a *member* we want see the attached identity. | URL
-
-**Returns**
-
-Identity data written in the blockchain.
-```json
-{
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "uid": "user identifier",
-  "sigDate": "21-EB18A8D89256EA80195990C91AD399B798F92EE8187F775DF7F4823C46E61F00"
-}
-```
-
-
-### blockchain/*
-
-#### `blockchain/parameters`
-
-**Goal**
-
-GET the blockchain parameters used by this node.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-The synchronization parameters.
-```json
-{
-  currency: "beta_brouzouf",
-  c: 0.01,
-  dt: 302400,
-  ud0: 100,
-  sigPeriod: 7200,
-  sigStock: 45,
-  sigWindow: 604800,
-  sigValidity: 2629800,
-  sigQty: 3,
-  idtyWindow: 604800,
-  msWindow: 604800,
-  xpercent: 5,
-  msValidity: 2629800,
-  stepMax: 3,
-  medianTimeBlocks: 11,
-  avgGenTime: 600,
-  dtDiffEval: 10,
-  percentRot: 0.67
-}
-```
-
-Parameters meaning is described under [Protocol parameters](./Protocol.md#protocol-parameters).
-
-#### `blockchain/membership`
-
-
-**Goal**
-
-POST a [Membership](./Protocol.md#membership) document.
-
-**Parameters**
-
-Name | Value | Method
----- | ----- | ------
-`membership` | The membership document (with signature). | POST
-
-**Returns**
-
-The posted membership request.
-```json
-{
-  "signature": "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
-  "membership": {
-    "version": "2",
-    "currency": "beta_brouzouf",
-    "issuer": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-    "membership": "IN",
-    "sigDate": 1390739944,
-    "uid": "superman63"
-  }
-}
-```
-
-#### `blockchain/memberships/[search]`
-
-
-**Goal**
-
-GET [Membership](./Protocol.md#membership) data written for a member.
-
-**Parameters**
-
-Name  | Value | Method
-----  | ----- | ------
-`search` | Public key or uid of a *member* we want see the memberships. | URL
-
-**Returns**
-
-A list of memberships issued by the *member* and written in the blockchain.
-```json
-{
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "uid": "user identifier",
-  "sigDate": 1390739944,
-  "memberships": [
-    {
-	  "version": "2",
-	  "currency": "beta_brouzouf",
-	  "membership": "IN",
-	  "blockNumber": 678,
-	  "blockHash": "000007936DF3CC32BFCC1023D1258EC9E485D474",
-	  "written_number": null
-	},
-    ...
-  ]
-}
-```
-
-#### `blockchain/block`
-
-**Goal**
-
-POST a new block to add to the blockchain.
-
-**Parameters**
-
-Name               | Value                          | Method
------------------- | ------------------------------ | ------
-`block`             | The raw block to be added     | POST
-`signature`         | Signature of the raw block    | POST
-
-**Returns**
-
-The promoted block if successfully added to the blockchain (see [block/[number]](#blockchainblocknumber) return object).
-
-#### `blockchain/block/[NUMBER]`
-
-**Goal**
-
-GET the promoted block whose number `NUMBER`.
-
-**Parameters**
-
-Name               | Value                                                         | Method
------------------- | ------------------------------------------------------------- | ------
-`NUMBER`           | The promoted block number (integer value) we want to see.  | URL
-
-**Returns**
-
-The promoted block if it exists (otherwise return HTTP 404).
-```json
-{
-  "version": 2,
-  "currency": "beta_brouzouf",
-  "nonce": 28,
-  "inner_hash": "FD09B0F7CEC5A575CA6E528DC4C854B612AE77B7283F48E0D28677F5C9C9D0DD",
-  "number": 1,
-  "time": 1408996317,
-  "medianTime": 1408992543,
-  "dividend": 254,
-  "monetaryMass": 18948,
-  "issuer": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "previousHash": "0009A7A62703F976F683BBA500FC0CB832B8220D",
-  "previousIssuer": "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp",
-  "membersCount": 4,
-  "hash": "0000F40BDC0399F2E84000468628F50A122B5F16",
-  "identities": [
-    "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:crowlin"
-  ],
-  "joiners": [
-    "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:crowlin"
-  ],
-  "leavers": [
-    "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:crowlin"
-  ],
-  "revoked": [
-    "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX"
-  ],
-  "excluded": [
-    "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB"
-  ],
-  "certifications": [
-    "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:1505900000:2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk"
-  ],
-  "transactions": [
-    {
-      "signatures": [
-        "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw=="
-        "2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX",
-        "2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk"
-      ],
-        "version": 2,
-        "currency": "beta_brouzouf",
-        "issuers": [
-          "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-          "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp",
-          "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB"
-        ],
-        "inputs": [
-          "T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:0",
-          "T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:0",
-          "D:4745EEBA84D4E3C2BDAE4768D4E0F5A671531EE1B0B9F5206744B4551C664FDF:243",
-          "T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:1",
-          "T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:0",
-          "D:521A760049DF4FAA602FEF86B7A8E306654502FA3A345F6169B8468B81E71AD3:187"
-       ],
-       "unlocks": [
-          "0:SIG(0)",
-          "1:SIG(2)",
-          "2:SIG(1)",
-          "3:SIG(1)",
-          "4:SIG(0)",
-          "5:SIG(0)"
-       ],
-      "outputs": [
-        "30:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)",
-        "156:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)",
-        "49:SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i)"
-      ]
-    }
-  ],
-  "signature": "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
-}
-```
-
-#### `blockchain/blocks/[COUNT]/[FROM]`
-
-**Goal**
-
-GET the `[COUNT]` promoted blocks from `[FROM]` number, inclusive.
-
-**Parameters**
-
-Name               | Value                                                         | Method
------------------- | ------------------------------------------------------------- | ------
-`COUNT`           | The number of blocks we want to see.  | URL
-`FROM`           | The starting block.  | URL
-
-**Returns**
-
-The promoted blocks if it exists block `[FROM]` (otherwise return HTTP 404). Result is an array whose values are the same structure as [/blockchain/block/[number]](#blockchainblocknumber).
-```json
-{
-  "blocks": [
-    { number: 2, ... },
-    { number: 3, ... }
-  ]
-}
-```
-
-#### `blockchain/current`
-
-Same as [block/[number]](#blockchainblocknumber), but return last accepted block.
-
-#### `blockchain/hardship/[PUBKEY]`
-
-**Goal**
-
-GET hardship level for given member's pubkey for writing next block.
-
-**Parameters**
-
-Name              | Value                     | Method
-----              | -----                     | ------
-`PUBKEY` | Member's pubkey.   | URL
-
-**Returns**
-
-The hardship value (`level`) + `block` number.
-```json
-{
-  "block": 598,
-  "level": 3
-}
-
-```
-
-#### `blockchain/difficulties`
-
-**Goal**
-
-GET hardship level for given member's pubkey for writing next block.
-
-**Parameters**
-
-None.
-
-**Returns**
-
-The respective difficulty of each member in the last `IssuersFrame` blocks for current block.
-```json
-{
-  "block": 598,
-  "levels": [{
-    "uid": "jack",
-    "level": 8
-  },{
-    "uid": "cat",
-    "level": 4
-  }]
-}
-
-```
-
-#### `blockchain/with/newcomers`
-**Goal**
-
-GET the block numbers containing newcomers (new identities).
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/with/certs`
-**Goal**
-
-GET the block numbers containing certifications.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/with/joiners`
-**Goal**
-
-GET the block numbers containing joiners (newcomers or people coming back after exclusion).
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/with/actives`
-**Goal**
-
-GET the block numbers containing actives (members updating their membership).
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/with/leavers`
-**Goal**
-
-GET the block numbers containing leavers (members leaving definitely the currency).
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/with/revoked`
-**Goal**
-
-GET the block numbers containing revoked members.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/with/excluded`
-**Goal**
-
-GET the block numbers containing excluded members.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/with/ud`
-**Goal**
-
-GET the block numbers containing Universal Dividend.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/with/tx`
-**Goal**
-
-GET the block numbers containing transactions.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Block numbers.
-```json
-{
-  "result": {
-    "blocks": [223,813]
-  }
-}
-```
-
-#### `blockchain/branches`
-
-**Goal**
-
-GET current branches of the node.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Top block of each branch, i.e. the last received block of each branch. An array of 4 blocks would mean the node has 4 branches,
-3 would mean 3 branches, and so on.
-
-```json
-{
-  "blocks": [
-    { number: 2, ... },
-    { number: 3, ... }
-  ]
-}
-```
-
-### network/*
-
-This URL is used for Duniter Gossip protocol (exchanging UCG messages).
-
-#### `network/peers`
-**Goal**
-
-GET the exhaustive list of peers known by the node.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-List of peering entries.
-```json
-{
-  "peers": [
-    {
-      "version": "2",
-      "currency": "meta_brouzouf",
-      "status": "UP",
-      "first_down": null,
-      "last_try": null,
-      "pubkey": "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk",
-      "block": "45180-00000E577DD4B308B98D0ED3E43926CE4D22E9A8",
-      "signature": "GKTrlUc4um9lQuj9UI8fyA/n/JKieYqBYcl9keIWfAVOnvHamLHaqGzijsdX1kNt64cadcle/zkd7xOgMTdQAQ==",
-      "endpoints": [
-        "BASIC_MERKLED_API metab.ucoin.io 88.174.120.187 9201"
-      ]
-    },
-    {
-      "version": "2",
-      "currency": "meta_brouzouf",
-      "status": "UP",
-      "first_down": null,
-      "last_try": null,
-      "pubkey": "2aeLmae5d466y8D42wLK5MknwUBCR6MWWeixRzdTQ4Hu",
-      "block": "45182-0000064EEF412C1CDD1B370CC45A3BC3B9743464",
-      "signature": "kbdTay1OirDqG/E3jyCaDlL7HVVHb9/BXvNHAg+xO9sSA+NgmBo/4mEqL9b7hH0UnbXHss6TfuvxAHZLmBqsCw==",
-      "endpoints": [
-        "BASIC_MERKLED_API twiced.fr 88.174.120.187 9223"
-      ]
-    },
-    ...
-  ]
-}
-```
-
-#### `network/peering`
-**Goal**
-
-GET the peering informations of this node.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Peering entry of the node.
-```json
-{
-  "version": "2",
-  "currency": "beta_brouzouf",
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "endpoints": [
-    "BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9001",
-    "BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9002",
-    "OTHER_PROTOCOL 88.77.66.55 9001",
-  ],
-  "signature": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r"
-}
-```
-
-#### `network/peering/peers (GET)`
-**Goal**
-
-Merkle URL refering to peering entries of every node inside the currency network.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Merkle URL result.
-```json
-{
-  "depth": 3,
-  "nodesCount": 6,
-  "leavesCount": 5,
-  "root": "114B6E61CB5BB93D862CA3C1DFA8B99E313E66E9"
-}
-```
-
-Merkle URL leaf: peering entry
-```json
-{
-  "hash": "2E69197FAB029D8669EF85E82457A1587CA0ED9C",
-  "value": {
-    "version": "2",
-    "currency": "beta_brouzouf",
-    "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-    "endpoints": [
-      "BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9001",
-      "BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9002",
-      "OTHER_PROTOCOL 88.77.66.55 9001",
-    ],
-    "signature": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r"
-  }
-}
-```
-
-#### `network/peering/peers (POST)`
-**Goal**
-
-POST a peering entry document.
-
-**Parameters**
-
-Name        | Value                               | Method
------------ | ----------------------------------- | ------
-`peer`      | The peering entry document.         | POST
-
-**Returns**
-
-The posted entry.
-```json
-{
-  "version": "2",
-  "currency": "beta_brouzouf",
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "endpoints": [
-    "BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9001",
-    "BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9002",
-    "OTHER_PROTOCOL 88.77.66.55 9001",
-  ],
-  "signature": "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r"
-}
-```
-
-### tx/*
-
-#### `tx/process`
-**Goal**
-
-POST a transaction.
-
-**Parameters**
-
-Name              | Value                                                         | Method
------------------ | ------------------------------------------------------------- | ------
-`transaction`     | The raw transaction.                                          | POST
-
-**Returns**
-
-The recorded transaction.
-```json
-{
-  "raw": "Version: 2\r\n...\r\n",
-  "transaction":
-  {
-      "signatures": [
-        "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw=="
-        "2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX",
-        "2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk"
-      ],
-        "version": 2,
-        "currency": "beta_brouzouf",
-        "issuers": [
-          "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-          "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp",
-          "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB"
-        ],
-        "inputs": [
-          "T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:0",
-          "T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:0",
-          "D:4745EEBA84D4E3C2BDAE4768D4E0F5A671531EE1B0B9F5206744B4551C664FDF:243",
-          "T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:1",
-          "T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:0",
-          "D:521A760049DF4FAA602FEF86B7A8E306654502FA3A345F6169B8468B81E71AD3:187"
-       ],
-       "unlocks": [
-          "0:SIG(0)",
-          "1:SIG(2)",
-          "2:SIG(1)",
-          "3:SIG(1)",
-          "4:SIG(0)",
-          "5:SIG(0)"
-       ],
-      "outputs": [
-        "30:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)",
-        "156:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)",
-        "49:SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i)"
-      ]
-  }
-}
-```
-
-
-#### `tx/sources/[pubkey]`
-
-**Goal**
-
-GET a list of available sources.
-
-**Parameters**
-
-Name              | Value                       | Method
-----              | -----                       | ------
-`pubkey`           | Owner of the coins' pubkey. | URL
-
-**Returns**
-
-A list of available sources for the given `pubkey`.
-```json
-{
-  "currency": "beta_brouzouf",
-  "pubkey": "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY",
-  "sources": [
-    {
-      "type: "D",
-      "noffset": 5,
-      "identifier": "6C20752F6AD06AEA8D0BB46BB8C4F68641A34C79",
-      "amount": 100
-    },
-    {
-      "type: "D",
-      "noffset": 18,
-      "identifier": "DB7D88E795E42CF8CFBFAAFC77379E97847F9B42",
-      "amount": 110
-    },
-    {
-      "type: "T",
-      "noffset": 55,
-      "identifier": "E614E814179F313B1113475E6319EF4A3D470AD0",
-      "amount": 30
-    }
-  ]
-}
-```
-
-
-#### `tx/history/[pubkey]`
-
-**Goal**
-
-Get the wallet transaction history
-
-**parameters**
-
-Name              | Value							| Method
-----              | -----							| ------
-`pubkey`          | Wallet public key.				| URL
-
-**Returns**
-
-The full transaction history for the given `pubkey`
-```json
-{
-  "currency": "meta_brouzouf",
-  "pubkey": "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk",
-  "history": {
-    "sent": [
-      {
-        "version": 2,
-        "received": null,
-        "issuers": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
-        ],
-        "inputs": [
-          "D:000A8362AE0C1B8045569CE07735DE4C18E81586:125"
-        ],
-        "outputs": [
-          "5:SIG(8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU)",
-          "95:SIG(HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk)"
-        ],
-        "comment": "Essai",
-        "signatures": [
-          "8zzWSU+GNSNURnH1NKPT/TBoxngEc/0wcpPSbs7FqknGxud+94knvT+dpe99k6NwyB5RXvOVnKAr4p9/KEluCw=="
-        ],
-        "hash": "FC7BAC2D94AC9C16AFC5C0150C2C9E7FBB2E2A09",
-        "block_number": 173,
-        "time": 1421932545
-      }
-    ],
-    "received": [
-      {
-        "version": 2,
-        "received": null,
-        "issuers": [
-          "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU"
-        ],
-        "inputs": [
-          "D:000A8362AE0C1B8045569CE07735DE4C18E81586:125"
-        ],
-        "outputs": [
-          "7:SIG(HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk)",
-          "93:SIG(8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU)"
-        ],
-        "comment": "",
-        "signatures": [
-          "1Mn8q3K7N+R4GZEpAUm+XSyty1Uu+BuOy5t7BIRqgZcKqiaxfhAUfDBOcuk2i4TJy1oA5Rntby8hDN+cUCpvDg=="
-        ],
-        "hash": "5FB3CB80A982E2BDFBB3EA94673A74763F58CB2A",
-        "block_number": 207,
-        "time": 1421955525
-      },
-      {
-        "version": 2,
-        "received": null,
-        "issuers": [
-          "J78bPUvLjxmjaEkdjxWLeENQtcfXm7iobqB49uT1Bgp3"
-        ],
-        "inputs": [
-          "T:6A50FF82410387B239489CE38B34E0FDDE1697FE:0"
-        ],
-        "outputs": [
-          "42:SIG(HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk)",
-          "9958:SIG(J78bPUvLjxmjaEkdjxWLeENQtcfXm7iobqB49uT1Bgp3)"
-        ],
-        "comment": "",
-        "signatures": [
-          "XhBcCPizPiWdKeXWg1DX/FTQst6DppEjsYEtoAZNA0P11reXtgc9IduiIxNWzNjt/KvTw8APkSI8/Uf31QQVDA=="
-        ],
-        "hash": "ADE7D1C4002D6BC10013C34CE22733A55173BAD4",
-        "block_number": 15778,
-        "time": 1432314584
-      }
-    ],
-    "sending": [
-	  {
-        "version": 2,
-        "received": 1459691641,
-        "issuers": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
-        ],
-        "inputs": [
-          "0:D:8196:000022AD426FE727C707D847EC2168A64C577706:5872"
-        ],
-        "outputs": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:5871"
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX:1",
-        ],
-        "comment": "some comment",
-        "signatures": [
-          "kLOAAy7/UldQk7zz4I7Jhv9ICuGYRx7upl8wH8RYL43MMF6+7MbPh3QRN1qNFGpAfa3XMWIQmbUWtjZKP6OfDA=="
-        ],
-        "hash": "BA41013F2CD38EDFFA9D38A275F8532DD906A2DE"
-      }
-    ],
-    "receiving": [
-	 {
-        "version": 2,
-        "received": 1459691641,
-        "issuers": [
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX"
-        ],
-        "inputs": [
-          "0:D:8196:000022AD426FE727C707D847EC2168A64C577706:4334"
-        ],
-        "outputs": [
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX:1",
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:4333"
-        ],
-        "comment": "some comment",
-        "signatures": [
-          "DRiZinUEKrrLiJNogtydzwEbmETrvWiLNYXCiJsRekxTLyU5g4LjnwiLp/XlvmIekjJK5n/gullLWrHUBvFSAw==
-        ],
-        "hash": "A0A511131CD0E837204A9441B3354918AC4CE671"
-      }
-	]
-  }
-}
-```
-
-#### `tx/history/[PUBKEY]/blocks/[from]/[to]`
-
-**Goal**
-
-Get the wallet transaction history
-
-**parameters**
-
-Name				| Value							| Method
-----				| -----							| ------
-`pubkey`			| Wallet public key.			| URL
-`from`				| The starting block.			| URL
-`to`				| the ending block.				| URL
-
-**Returns**
-
-The transaction history for the given `pubkey` and between the given `from` and `to` blocks. 
-```json
-{
-  "currency": "meta_brouzouf",
-  "pubkey": "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk",
-  "history": {
-    "sent": [
-      {
-        "version": 2,
-        "issuers": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
-        ],
-        "inputs": [
-          "0:D:125:000A8362AE0C1B8045569CE07735DE4C18E81586:100"
-        ],
-        "outputs": [
-          "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU:5",
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:95"
-        ],
-        "comment": "Essai",
-        "signatures": [
-          "8zzWSU+GNSNURnH1NKPT/TBoxngEc/0wcpPSbs7FqknGxud+94knvT+dpe99k6NwyB5RXvOVnKAr4p9/KEluCw=="
-        ],
-        "hash": "FC7BAC2D94AC9C16AFC5C0150C2C9E7FBB2E2A09",
-        "block_number": 173,
-        "time": 1421932545
-      }
-    ],
-    "received": [
-      {
-        "version": 2,
-        "issuers": [
-          "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU"
-        ],
-        "inputs": [
-          "0:D:125:000A8362AE0C1B8045569CE07735DE4C18E81586:100"
-        ],
-        "outputs": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:7",
-          "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU:93"
-        ],
-        "comment": "",
-        "signatures": [
-          "1Mn8q3K7N+R4GZEpAUm+XSyty1Uu+BuOy5t7BIRqgZcKqiaxfhAUfDBOcuk2i4TJy1oA5Rntby8hDN+cUCpvDg=="
-        ],
-        "hash": "5FB3CB80A982E2BDFBB3EA94673A74763F58CB2A",
-        "block_number": 207,
-        "time": 1421955525
-      },
-      {
-        "version": 2,
-        "issuers": [
-          "J78bPUvLjxmjaEkdjxWLeENQtcfXm7iobqB49uT1Bgp3"
-        ],
-        "inputs": [
-          "0:T:15128:6A50FF82410387B239489CE38B34E0FDDE1697FE:10000"
-        ],
-        "outputs": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:42",
-          "J78bPUvLjxmjaEkdjxWLeENQtcfXm7iobqB49uT1Bgp3:9958"
-        ],
-        "comment": "",
-        "signatures": [
-          "XhBcCPizPiWdKeXWg1DX/FTQst6DppEjsYEtoAZNA0P11reXtgc9IduiIxNWzNjt/KvTw8APkSI8/Uf31QQVDA=="
-        ],
-        "hash": "ADE7D1C4002D6BC10013C34CE22733A55173BAD4",
-        "block_number": 15778,
-        "time": 1432314584
-      }
-    ],
-    "sending": [
-	  {
-        "version": 2,
-        "issuers": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
-        ],
-        "inputs": [
-          "0:D:8196:000022AD426FE727C707D847EC2168A64C577706:5872"
-        ],
-        "outputs": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:5871"
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX:1",
-        ],
-        "comment": "some comment",
-        "signatures": [
-          "kLOAAy7/UldQk7zz4I7Jhv9ICuGYRx7upl8wH8RYL43MMF6+7MbPh3QRN1qNFGpAfa3XMWIQmbUWtjZKP6OfDA=="
-        ],
-        "hash": "BA41013F2CD38EDFFA9D38A275F8532DD906A2DE"
-      }
-    ],
-    "receiving": [
-	 {
-        "version": 2,
-        "issuers": [
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX"
-        ],
-        "inputs": [
-          "0:D:8196:000022AD426FE727C707D847EC2168A64C577706:4334"
-        ],
-        "outputs": [
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX:1",
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:4333"
-        ],
-        "comment": "some comment",
-        "signatures": [
-          "DRiZinUEKrrLiJNogtydzwEbmETrvWiLNYXCiJsRekxTLyU5g4LjnwiLp/XlvmIekjJK5n/gullLWrHUBvFSAw==
-        ],
-        "hash": "A0A511131CD0E837204A9441B3354918AC4CE671"
-      }
-	]
-  }
-}
-```
-
-#### `tx/history/[pubkey]/times/[from]/[to]`
-
-**Goal**
-
-Get the wallet transaction history
-
-**parameters**
-
-Name              | Value							| Method
-----              | -----							| ------
-`pubkey`          | Wallet public key.				| URL
-`from` | The starting timestamp limit. (optionnal) | URL
-`to`        | The ending timestamp. (optionnal)	| URL
-
-**Returns**
-
-The transaction history for the given `pubkey` and between the given `from` and `to` dates. 
-```json
-{
-  "currency": "meta_brouzouf",
-  "pubkey": "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk",
-  "history": {
-    "sent": [
-      {
-        "version": 2,
-        "issuers": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
-        ],
-        "inputs": [
-          "0:D:125:000A8362AE0C1B8045569CE07735DE4C18E81586:100"
-        ],
-        "outputs": [
-          "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU:5",
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:95"
-        ],
-        "comment": "Essai",
-        "signatures": [
-          "8zzWSU+GNSNURnH1NKPT/TBoxngEc/0wcpPSbs7FqknGxud+94knvT+dpe99k6NwyB5RXvOVnKAr4p9/KEluCw=="
-        ],
-        "hash": "FC7BAC2D94AC9C16AFC5C0150C2C9E7FBB2E2A09",
-        "block_number": 173,
-        "time": 1421932545
-      }
-    ],
-    "received": [
-      {
-        "version": 2,
-        "issuers": [
-          "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU"
-        ],
-        "inputs": [
-          "0:D:125:000A8362AE0C1B8045569CE07735DE4C18E81586:100"
-        ],
-        "outputs": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:7",
-          "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU:93"
-        ],
-        "comment": "",
-        "signatures": [
-          "1Mn8q3K7N+R4GZEpAUm+XSyty1Uu+BuOy5t7BIRqgZcKqiaxfhAUfDBOcuk2i4TJy1oA5Rntby8hDN+cUCpvDg=="
-        ],
-        "hash": "5FB3CB80A982E2BDFBB3EA94673A74763F58CB2A",
-        "block_number": 207,
-        "time": 1421955525
-      },
-      {
-        "version": 2,
-        "issuers": [
-          "J78bPUvLjxmjaEkdjxWLeENQtcfXm7iobqB49uT1Bgp3"
-        ],
-        "inputs": [
-          "0:T:15128:6A50FF82410387B239489CE38B34E0FDDE1697FE:10000"
-        ],
-        "outputs": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:42",
-          "J78bPUvLjxmjaEkdjxWLeENQtcfXm7iobqB49uT1Bgp3:9958"
-        ],
-        "comment": "",
-        "signatures": [
-          "XhBcCPizPiWdKeXWg1DX/FTQst6DppEjsYEtoAZNA0P11reXtgc9IduiIxNWzNjt/KvTw8APkSI8/Uf31QQVDA=="
-        ],
-        "hash": "ADE7D1C4002D6BC10013C34CE22733A55173BAD4",
-        "block_number": 15778,
-        "time": 1432314584
-      }
-    ],
-    "sending": [
-	  {
-        "version": 2,
-        "issuers": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
-        ],
-        "inputs": [
-          "0:D:8196:000022AD426FE727C707D847EC2168A64C577706:5872"
-        ],
-        "outputs": [
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:5871"
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX:1",
-        ],
-        "comment": "some comment",
-        "signatures": [
-          "kLOAAy7/UldQk7zz4I7Jhv9ICuGYRx7upl8wH8RYL43MMF6+7MbPh3QRN1qNFGpAfa3XMWIQmbUWtjZKP6OfDA=="
-        ],
-        "hash": "BA41013F2CD38EDFFA9D38A275F8532DD906A2DE"
-      }
-    ],
-    "receiving": [
-	 {
-        "version": 2,
-        "issuers": [
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX"
-        ],
-        "inputs": [
-          "0:D:8196:000022AD426FE727C707D847EC2168A64C577706:4334"
-        ],
-        "outputs": [
-          "2sq8bBDQGK74f1eD3mAPQVgHCmFdijZr9nbv16FwbokX:1",
-          "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:4333"
-        ],
-        "comment": "some comment",
-        "signatures": [
-          "DRiZinUEKrrLiJNogtydzwEbmETrvWiLNYXCiJsRekxTLyU5g4LjnwiLp/XlvmIekjJK5n/gullLWrHUBvFSAw==
-        ],
-        "hash": "A0A511131CD0E837204A9441B3354918AC4CE671"
-      }
-	]
-  }
-}
-```
-### ud/*
-
-#### `ud/history/[pubkey]`
-
-**Goal**
-
-Get the wallet universal dividend history
-
-**parameters**
-
-Name              | Value							| Method
-----              | -----							| ------
-`pubkey`          | Wallet public key.				| URL
-
-**Returns**
-
-The universal dividend history for the given `pubkey`. 
-```json
-{
-  "currency": "meta_brouzouf",
-  "pubkey": "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk",
-  "history": {
-    "history": [
-      {
-        "block_number": 125,
-        "consumed": true,
-        "time": 1421927007,
-        "amount": 100
-      },
-      {
-        "block_number": 410,
-        "consumed": false,
-        "time": 1422012828,
-        "amount": 100
-      },
-      {
-        "block_number": 585,
-        "consumed": true,
-        "time": 1422098800,
-        "amount": 100
-      }
-    ]
-  }
-}
-```
-
-
-### ws/*
-
-#### `ws/block`
-
-**Goal**
-
-A websocket entry point for receiving blocks.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Websocket connection.
-
-#### `ws/peer`
-
-**Goal**
-
-A websocket entry point for receiving peers.
-
-**Parameters**
-
-*None*.
-
-**Returns**
-
-Websocket connection.
diff --git a/index.js b/index.js
index 512d77e1c..b6737e398 100644
--- a/index.js
+++ b/index.js
@@ -26,7 +26,7 @@ const daemonDependency    = require('./app/modules/daemon');
 const pSignalDependency   = require('./app/modules/peersignal');
 const crawlerDependency   = require('./app/modules/crawler');
 const proverDependency    = require('./app/modules/prover');
-const bmapiDependency     = require('./app/modules/bmapi');
+const bmapiDependency     = require('duniter-bma');
 const routerDependency    = require('./app/modules/router');
 
 const MINIMAL_DEPENDENCIES = [
@@ -326,14 +326,6 @@ function commandLineConf(program, conf) {
     cpu: program.cpu,
     server: {
       port: program.port,
-      ipv4address: program.ipv4,
-      ipv6address: program.ipv6,
-      remote: {
-        host: program.remoteh,
-        ipv4: program.remote4,
-        ipv6: program.remote6,
-        port: program.remotep
-      }
     },
     db: {
       mport: program.mport,
@@ -354,13 +346,7 @@ function commandLineConf(program, conf) {
 
   // Update conf
   if (cli.currency)                         conf.currency = cli.currency;
-  if (cli.server.ipv4address)               conf.ipv4 = cli.server.ipv4address;
-  if (cli.server.ipv6address)               conf.ipv6 = cli.server.ipv6address;
   if (cli.server.port)                      conf.port = cli.server.port;
-  if (cli.server.remote.host != undefined)  conf.remotehost = cli.server.remote.host;
-  if (cli.server.remote.ipv4 != undefined)  conf.remoteipv4 = cli.server.remote.ipv4;
-  if (cli.server.remote.ipv6 != undefined)  conf.remoteipv6 = cli.server.remote.ipv6;
-  if (cli.server.remote.port != undefined)  conf.remoteport = cli.server.remote.port;
   if (cli.cpu)                              conf.cpu = Math.max(0.01, Math.min(1.0, cli.cpu));
   if (cli.logs.http)                        conf.httplogs = true;
   if (cli.logs.nohttp)                      conf.httplogs = false;
diff --git a/package.json b/package.json
index bb7af9947..fe9ee7dc9 100644
--- a/package.json
+++ b/package.json
@@ -38,27 +38,19 @@
     "archiver": "1.0.1",
     "async": "1.5.2",
     "bindings": "1.2.1",
-    "body-parser": "1.15.2",
     "co": "4.6.0",
     "colors": "1.1.2",
     "commander": "2.9.0",
-    "cors": "2.8.1",
     "daemonize2": "0.4.2",
-    "ddos": "0.1.16",
     "duniter-keypair": "duniter/duniter-keypair",
-    "errorhandler": "1.4.3",
+    "duniter-bma": "duniter/duniter-bma",
     "event-stream": "3.3.4",
-    "express": "4.14.0",
-    "express-cors": "0.0.3",
-    "express-fileupload": "0.0.5",
     "inquirer": "0.8.5",
     "jison": "0.4.17",
     "merkle": "0.5.1",
     "moment": "2.15.1",
-    "morgan": "1.7.0",
     "multimeter": "0.1.1",
     "naclb": "1.3.7",
-    "nnupnp": "1.0.2",
     "node-pre-gyp": "0.6.32",
     "node-uuid": "1.4.7",
     "optimist": "0.6.1",
@@ -75,8 +67,7 @@
     "unzip": "0.1.11",
     "unzip2": "0.2.5",
     "winston": "2.2.0",
-    "wotb": "0.4.14",
-    "ws": "1.1.1"
+    "wotb": "0.4.14"
   },
   "devDependencies": {
     "coveralls": "2.11.4",
diff --git a/server.js b/server.js
index 46289b304..f9566ccbf 100644
--- a/server.js
+++ b/server.js
@@ -35,17 +35,21 @@ function Server (home, memoryOnly, overrideConf) {
   that.lib = {};
   that.lib.keyring = require('./app/lib/crypto/keyring');
   that.lib.Identity = require('./app/lib/entity/identity');
+  that.lib.Transaction = require('./app/lib/entity/transaction');
+  that.lib.Peer = require('./app/lib/entity/peer');
+  that.lib.Membership = require('./app/lib/entity/membership');
+  that.lib.Block = require('./app/lib/entity/block');
+  that.lib.Stat = require('./app/lib/entity/stat');
   that.lib.rawer = require('./app/lib/ucp/rawer');
-  that.lib.http2raw = require('./app/lib/helpers/http2raw');
+  that.lib.http2raw = require('duniter-bma').duniter.methods.http2raw;
   that.lib.dos2unix = require('./app/lib/system/dos2unix');
   that.lib.contacter = require('./app/lib/contacter');
-  that.lib.bma = require('./app/lib/streams/bma');
+  that.lib.bma = require('duniter-bma').duniter.methods.bma;
   that.lib.network = require('./app/lib/system/network');
   that.lib.constants = require('./app/lib/constants');
   that.lib.ucp = require('./app/lib/ucp/buid');
 
   that.MerkleService       = require("./app/lib/helpers/merkle");
-  that.ParametersService   = require("./app/lib/helpers/parameters")();
   that.IdentityService     = require('./app/service/IdentityService')();
   that.MembershipService   = require('./app/service/MembershipService')();
   that.PeeringService      = require('./app/service/PeeringService')(that);
@@ -189,19 +193,9 @@ function Server (home, memoryOnly, overrideConf) {
   this.isServerMember = () => this.BlockchainService.isMember();
 
   this.checkConfig = () => co(function*() {
-    const conf = that.conf;
-    if (!conf.pair) {
+    if (!that.conf.pair) {
       throw new Error('No keypair was given.');
     }
-    if(!conf.ipv4 && !conf.ipv6){
-      throw new Error("No interface to listen to.");
-    }
-    if(!conf.remoteipv4 && !conf.remoteipv6 && !conf.remotehost){
-      throw new Error('No interface for remote contact.');
-    }
-    if (!conf.remoteport) {
-      throw new Error('No port for remote contact.');
-    }
   });
 
   this.resetHome = () => co(function *() {
diff --git a/test/dal/triming.js b/test/dal/triming.js
index 50ed30d28..770a34401 100644
--- a/test/dal/triming.js
+++ b/test/dal/triming.js
@@ -5,7 +5,6 @@ const FileDAL = require('../../app/lib/dal/fileDAL');
 const dir = require('../../app/lib/system/directory');
 const indexer = require('../../app/lib/dup/indexer');
 const toolbox = require('../integration/tools/toolbox');
-const limiter = require('../../app/lib/system/limiter');
 
 let dal;
 
@@ -14,7 +13,6 @@ describe("Triming", function(){
   before(() => co(function *() {
     dal = FileDAL(yield dir.getHomeParams(true, 'db0'));
     yield dal.init();
-    limiter.noLimit();
   }));
 
   it('should be able to feed the bindex', () => co(function *() {
diff --git a/test/fast/ddos-test.js b/test/fast/ddos-test.js
deleted file mode 100644
index 73e3f8d90..000000000
--- a/test/fast/ddos-test.js
+++ /dev/null
@@ -1,39 +0,0 @@
-"use strict";
-const should = require('should');
-const co = require('co');
-const limiter = require('../../app/lib/system/limiter');
-const toolbox = require('../integration/tools/toolbox');
-const user    = require('../integration/tools/user');
-const bma     = require('../../app/lib/streams/bma');
-
-limiter.noLimit();
-
-const s1 = toolbox.server({
-  pair: {
-    pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
-    sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP'
-  }
-});
-
-describe('DDOS', () => {
-
-  before(() => co(function*() {
-    limiter.noLimit();
-    yield s1.initWithDAL().then(bma).then((bmapi) => {
-      s1.bma = bmapi;
-      bmapi.openConnections();
-    });
-  }));
-
-  it('should not be able to send more than 4 reqs/s', () => co(function*() {
-    try {
-      s1.bma.getDDOS().params.limit = 3;
-      s1.bma.getDDOS().params.burst = 3;
-      s1.bma.getDDOS().params.whitelist = [];
-      yield Array.from({ length: 4 }).map(() => s1.get('/blockchain/current'));
-      throw 'Wrong error thrown';
-    } catch (e) {
-      e.should.have.property('statusCode').equal(429);
-    }
-  }));
-});
diff --git a/test/fast/limiter-test.js b/test/fast/limiter-test.js
deleted file mode 100644
index efc1ca239..000000000
--- a/test/fast/limiter-test.js
+++ /dev/null
@@ -1,60 +0,0 @@
-"use strict";
-const should = require('should');
-const co = require('co');
-const limiter = require('../../app/lib/system/limiter');
-const toolbox = require('../integration/tools/toolbox');
-const user    = require('../integration/tools/user');
-const bma     = require('../../app/lib/streams/bma');
-
-limiter.noLimit();
-
-const s1 = toolbox.server({
-  pair: {
-    pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
-    sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP'
-  }
-});
-
-const cat = user('cat', { pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP'}, { server: s1 });
-
-let theLimiter;
-
-describe('Limiter', () => {
-
-  before(() => {
-    limiter.withLimit();
-    theLimiter = limiter.limitAsTest();
-  });
-
-  it('should not be able to send more than 10 reqs/s', () => {
-    theLimiter.canAnswerNow().should.equal(true);
-    for (let i = 1; i <= 4; i++) {
-        theLimiter.processRequest();
-    }
-    theLimiter.canAnswerNow().should.equal(true);
-    theLimiter.processRequest(); // 5 in 1sec
-    theLimiter.canAnswerNow().should.equal(false);
-  });
-
-  it('should be able to send 1 more request (by minute constraint)', () => co(function*(){
-    yield new Promise((resolve) => setTimeout(resolve, 1000));
-    theLimiter.canAnswerNow().should.equal(true);
-    theLimiter.processRequest(); // 1 in 1sec, 6 in 1min
-    theLimiter.canAnswerNow().should.equal(false);
-  }));
-
-  it('should work with BMA API', () => co(function*(){
-    yield s1.initWithDAL().then(bma).then((bmapi) => bmapi.openConnections());
-    yield cat.createIdentity();
-    try {
-      for (let i = 0; i < 11; i++) {
-        yield s1.get('/wot/lookup/cat');
-      }
-      throw 'Should have thrown a limiter error';
-    } catch (e) {
-      e.should.have.property('error').property('ucode').equal(1006);
-    }
-  }));
-
-  after(() => limiter.noLimit());
-});
diff --git a/test/integration/branches.js b/test/integration/branches.js
index 480009199..0db977f6a 100644
--- a/test/integration/branches.js
+++ b/test/integration/branches.js
@@ -4,7 +4,7 @@ const _         = require('underscore');
 const co        = require('co');
 const should    = require('should');
 const duniter   = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
 
diff --git a/test/integration/branches2.js b/test/integration/branches2.js
index 5dcc3804f..e31619514 100644
--- a/test/integration/branches2.js
+++ b/test/integration/branches2.js
@@ -3,7 +3,7 @@
 const co        = require('co');
 const _         = require('underscore');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const constants = require('../../app/lib/constants');
 const rp        = require('request-promise');
diff --git a/test/integration/branches_pending_data.js b/test/integration/branches_pending_data.js
index 83c87585b..9cf29a9b0 100644
--- a/test/integration/branches_pending_data.js
+++ b/test/integration/branches_pending_data.js
@@ -3,7 +3,7 @@
 const co = require('co');
 const _         = require('underscore');
 const duniter   = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
diff --git a/test/integration/branches_revert.js b/test/integration/branches_revert.js
index 7a174e8ba..ed00d5e76 100644
--- a/test/integration/branches_revert.js
+++ b/test/integration/branches_revert.js
@@ -2,7 +2,7 @@
 
 const co = require('co');
 const _         = require('underscore');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const toolbox   = require('./tools/toolbox');
 const commit    = require('./tools/commit');
diff --git a/test/integration/branches_revert2.js b/test/integration/branches_revert2.js
index 89db2d780..8dddeff3e 100644
--- a/test/integration/branches_revert2.js
+++ b/test/integration/branches_revert2.js
@@ -3,7 +3,7 @@
 const co = require('co');
 const _         = require('underscore');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
diff --git a/test/integration/branches_revert_memberships.js b/test/integration/branches_revert_memberships.js
index 298afd8ac..4b12f96d8 100644
--- a/test/integration/branches_revert_memberships.js
+++ b/test/integration/branches_revert_memberships.js
@@ -2,11 +2,10 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const commit    = require('./tools/commit');
 const toolbox   = require('./tools/toolbox');
-const limiter   = require('../../app/lib/system/limiter');
 
 const s1 = toolbox.server({
   memory: true,
@@ -27,8 +26,6 @@ describe("Revert memberships", function() {
 
   before(() => co(function*() {
 
-    limiter.noLimit();
-
     yield s1.initWithDAL().then(bma).then((bmapi) => bmapi.openConnections());
 
     yield i1.createIdentity();
diff --git a/test/integration/branches_switch.js b/test/integration/branches_switch.js
index 0bcd556d6..d19a35aa6 100644
--- a/test/integration/branches_switch.js
+++ b/test/integration/branches_switch.js
@@ -3,7 +3,7 @@
 const co = require('co');
 const _         = require('underscore');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
diff --git a/test/integration/certification_chainability.js b/test/integration/certification_chainability.js
index 0b6e71f54..5731249fd 100644
--- a/test/integration/certification_chainability.js
+++ b/test/integration/certification_chainability.js
@@ -4,7 +4,7 @@ const _         = require('underscore');
 const co        = require('co');
 const should    = require('should');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const constants = require('../../app/lib/constants');
 const rp        = require('request-promise');
diff --git a/test/integration/collapse.js b/test/integration/collapse.js
index 56cfd9115..9b602e302 100644
--- a/test/integration/collapse.js
+++ b/test/integration/collapse.js
@@ -3,7 +3,7 @@
 const co        = require('co');
 const _         = require('underscore');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const commit    = require('./tools/commit');
 const httpTest  = require('./tools/http');
diff --git a/test/integration/crosschain-test.js b/test/integration/crosschain-test.js
index 0293a2079..2f0861781 100644
--- a/test/integration/crosschain-test.js
+++ b/test/integration/crosschain-test.js
@@ -5,7 +5,7 @@ const _ = require('underscore');
 const assert = require('assert');
 const should = require('should');
 const rp        = require('request-promise');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const commit    = require('./tools/commit');
 const toolbox = require('./tools/toolbox');
 const user   = require('./tools/user');
diff --git a/test/integration/forwarding.js b/test/integration/forwarding.js
index 605b43944..8ac1a4723 100644
--- a/test/integration/forwarding.js
+++ b/test/integration/forwarding.js
@@ -7,9 +7,6 @@ const co     = require('co');
 const node   = require('./tools/node');
 const user   = require('./tools/user');
 const jspckg = require('../../package');
-const limiter = require('../../app/lib/system/limiter');
-
-limiter.noLimit();
 
 const MEMORY_MODE = true;
 
@@ -17,7 +14,7 @@ describe("Forwarding", function() {
 
   describe("Nodes", function() {
 
-    const common = { currency: 'bb', ipv4: '127.0.0.1', remoteipv4: '127.0.0.1', upnp: false, rootoffset: 0, sigQty: 1 };
+    const common = { currency: 'bb', ipv4: '127.0.0.1', remoteipv4: '127.0.0.1', rootoffset: 0, sigQty: 1 };
 
     const node1 = node({ name: 'db_1', memory: MEMORY_MODE }, _({ httplogs: false, port: 9600, remoteport: 9600, pair: { pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP'} }).extend(common));
     const node2 = node({ name: 'db_2', memory: MEMORY_MODE }, _({ httplogs: false, port: 9601, remoteport: 9601, pair: { pub: 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU', sec: '58LDg8QLmF5pv6Dn9h7X4yFKfMTdP8fdAiWVcyDoTRJu454fwRihCLULH4MW37zncsg4ruoTGJPZneWk22QmG1w4'} }).extend(common));
diff --git a/test/integration/http_api.js b/test/integration/http_api.js
index 8a3e3d563..7ff64280d 100644
--- a/test/integration/http_api.js
+++ b/test/integration/http_api.js
@@ -5,7 +5,7 @@ const _         = require('underscore');
 const should    = require('should');
 const assert    = require('assert');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const http      = require('./tools/http');
 const constants = require('../../app/lib/constants');
diff --git a/test/integration/identity-absorption.js b/test/integration/identity-absorption.js
index 518c7249c..3150b9b70 100644
--- a/test/integration/identity-absorption.js
+++ b/test/integration/identity-absorption.js
@@ -3,7 +3,7 @@
 const _         = require('underscore');
 const co        = require('co');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
diff --git a/test/integration/identity-clean-test.js b/test/integration/identity-clean-test.js
index a217197e9..2ee0fc136 100644
--- a/test/integration/identity-clean-test.js
+++ b/test/integration/identity-clean-test.js
@@ -3,7 +3,7 @@
 const _         = require('underscore');
 const co        = require('co');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
diff --git a/test/integration/identity-expiry.js b/test/integration/identity-expiry.js
index 4875faf1a..c43753cdd 100644
--- a/test/integration/identity-expiry.js
+++ b/test/integration/identity-expiry.js
@@ -4,7 +4,7 @@ const _         = require('underscore');
 const co        = require('co');
 const should    = require('should');
 const duniter   = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const constants = require('../../app/lib/constants');
 const rp        = require('request-promise');
diff --git a/test/integration/identity-kicking.js b/test/integration/identity-kicking.js
index 96fb97c41..45f7f4b04 100644
--- a/test/integration/identity-kicking.js
+++ b/test/integration/identity-kicking.js
@@ -4,7 +4,7 @@ const _         = require('underscore');
 const co        = require('co');
 const should    = require('should');
 const duniter   = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const constants = require('../../app/lib/constants');
 const rp        = require('request-promise');
diff --git a/test/integration/identity-same-pubkey.js b/test/integration/identity-same-pubkey.js
index b2c014758..f64e9fc77 100644
--- a/test/integration/identity-same-pubkey.js
+++ b/test/integration/identity-same-pubkey.js
@@ -2,7 +2,7 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const commit    = require('./tools/commit');
 const toolbox   = require('./tools/toolbox');
diff --git a/test/integration/identity-test.js b/test/integration/identity-test.js
index bf62d7955..72e8aa705 100644
--- a/test/integration/identity-test.js
+++ b/test/integration/identity-test.js
@@ -4,15 +4,12 @@ const _         = require('underscore');
 const co        = require('co');
 const should    = require('should');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const constants = require('../../app/lib/constants');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
 const commit    = require('./tools/commit');
-const limiter = require('../../app/lib/system/limiter');
-
-limiter.noLimit();
 
 const expectAnswer   = httpTest.expectAnswer;
 
diff --git a/test/integration/lookup.js b/test/integration/lookup.js
index c30dcc477..84fdf26c1 100644
--- a/test/integration/lookup.js
+++ b/test/integration/lookup.js
@@ -3,7 +3,7 @@
 const _         = require('underscore');
 const co        = require('co');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
diff --git a/test/integration/network.js b/test/integration/network.js
index ecc54a25a..4e67e182c 100644
--- a/test/integration/network.js
+++ b/test/integration/network.js
@@ -23,6 +23,7 @@ const s1 = node({
   memory: MEMORY_MODE,
   name: 'bb33'
 }, _.extend({
+  ipv4: '127.0.0.1',
   port: '20501',
   remoteport: '20501',
   pair: {
diff --git a/test/integration/peer-outdated.js b/test/integration/peer-outdated.js
index 7c7e7112d..d0897a161 100644
--- a/test/integration/peer-outdated.js
+++ b/test/integration/peer-outdated.js
@@ -5,7 +5,7 @@ const Q         = require('q');
 const should    = require('should');
 const es        = require('event-stream');
 const _         = require('underscore');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const commit    = require('./tools/commit');
 const until     = require('./tools/until');
diff --git a/test/integration/peerings.js b/test/integration/peerings.js
index e963b555f..b296c807d 100644
--- a/test/integration/peerings.js
+++ b/test/integration/peerings.js
@@ -5,7 +5,7 @@ const Q         = require('q');
 const _         = require('underscore');
 const should    = require('should');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const constants = require('../../app/lib/constants');
 const rp        = require('request-promise');
diff --git a/test/integration/peers-same-pubkey.js b/test/integration/peers-same-pubkey.js
index cd16aa371..1d9f0ad54 100644
--- a/test/integration/peers-same-pubkey.js
+++ b/test/integration/peers-same-pubkey.js
@@ -4,7 +4,7 @@ const co        = require('co');
 const Q         = require('q');
 const _         = require('underscore');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const commit    = require('./tools/commit');
 const sync      = require('./tools/sync');
diff --git a/test/integration/revocation-test.js b/test/integration/revocation-test.js
index 7ed26cc63..61d39215c 100644
--- a/test/integration/revocation-test.js
+++ b/test/integration/revocation-test.js
@@ -4,14 +4,11 @@ const _         = require('underscore');
 const co        = require('co');
 const should    = require('should');
 const duniter   = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
 const commit    = require('./tools/commit');
-const limiter = require('../../app/lib/system/limiter');
-
-limiter.noLimit();
 
 const expectAnswer  = httpTest.expectAnswer;
 
diff --git a/test/integration/server-import-export.js b/test/integration/server-import-export.js
index c0372d89e..d00adeb6e 100644
--- a/test/integration/server-import-export.js
+++ b/test/integration/server-import-export.js
@@ -6,7 +6,7 @@ const co = require('co');
 const unzip = require('unzip');
 const toolbox = require('../integration/tools/toolbox');
 const user    = require('../integration/tools/user');
-const bma     = require('../../app/lib/streams/bma');
+const bma     = require('duniter-bma').duniter.methods.bma;
 
 const serverConfig = {
   memory: false,
diff --git a/test/integration/server-sandbox.js b/test/integration/server-sandbox.js
index 26c9f5338..e6dc5d9e1 100644
--- a/test/integration/server-sandbox.js
+++ b/test/integration/server-sandbox.js
@@ -2,14 +2,11 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const commit    = require('./tools/commit');
 const toolbox   = require('./tools/toolbox');
 const constants = require('../../app/lib/constants');
-const limiter   = require('../../app/lib/system/limiter');
-
-limiter.noLimit();
 
 const s1 = toolbox.server({
   idtyWindow: 10,
diff --git a/test/integration/start_generate_blocks.js b/test/integration/start_generate_blocks.js
index 8aebbcdb7..ede15accc 100644
--- a/test/integration/start_generate_blocks.js
+++ b/test/integration/start_generate_blocks.js
@@ -3,7 +3,7 @@
 const co        = require('co');
 const _         = require('underscore');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const rp        = require('request-promise');
 const httpTest  = require('./tools/http');
diff --git a/test/integration/tests.js b/test/integration/tests.js
index d7f019a75..7e81633d6 100644
--- a/test/integration/tests.js
+++ b/test/integration/tests.js
@@ -4,7 +4,7 @@ const co = require('co');
 const _ = require('underscore');
 const should = require('should');
 const assert = require('assert');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const constants = require('../../app/lib/constants');
 const node   = require('./tools/node');
 const duniter     = require('../../index');
@@ -13,9 +13,6 @@ const jspckg = require('../../package');
 const commit    = require('./tools/commit');
 const httpTest  = require('./tools/http');
 const rp        = require('request-promise');
-const limiter = require('../../app/lib/system/limiter');
-
-limiter.noLimit();
 
 const expectAnswer   = httpTest.expectAnswer;
 const MEMORY_MODE = true;
diff --git a/test/integration/tools/node.js b/test/integration/tools/node.js
index fc65b020f..63b2be1ad 100644
--- a/test/integration/tools/node.js
+++ b/test/integration/tools/node.js
@@ -13,7 +13,7 @@ var Configuration = require('../../../app/lib/entity/configuration');
 var Peer          = require('../../../app/lib/entity/peer');
 var user   = require('./user');
 var http   = require('./http');
-const bma = require('../../../app/lib/streams/bma');
+const bma = require('duniter-bma').duniter.methods.bma;
 
 module.exports = function (dbName, options) {
   return new Node(dbName, options);
@@ -146,6 +146,13 @@ function Node (dbName, options) {
         duniter: {
           config: {
             onLoading: (conf, program) => co(function*() {
+              options.port = options.port || 8999;
+              options.ipv4 = options.ipv4 || "127.0.0.1";
+              options.ipv6 = options.ipv6 || null;
+              options.remotehost = options.remotehost || null;
+              options.remoteipv4 = options.remoteipv4 || null;
+              options.remoteipv6 = options.remoteipv6 || null;
+              options.remoteport = options.remoteport || 8999;
               const overConf = Configuration.statics.complete(options);
               _.extend(conf, overConf);
             })
diff --git a/test/integration/tools/toolbox.js b/test/integration/tools/toolbox.js
index 0a5365381..d899f12b3 100644
--- a/test/integration/tools/toolbox.js
+++ b/test/integration/tools/toolbox.js
@@ -12,11 +12,14 @@ const until       = require('../tools/until');
 const Peer        = require('../../../app/lib/entity/peer');
 const Identity    = require('../../../app/lib/entity/identity');
 const Block       = require('../../../app/lib/entity/block');
-const bma         = require('../../../app/lib/streams/bma');
+const bma         = require('duniter-bma').duniter.methods.bma;
 const multicaster = require('../../../app/lib/streams/multicaster');
 const network     = require('../../../app/lib/system/network');
-const dtos        = require('../../../app/lib/streams/dtos');
+const dtos        = require('duniter-bma').duniter.methods.dtos;
 const duniter     = require('../../../index');
+const logger      = require('../../../app/lib/logger')('toolbox');
+
+require('duniter-bma').duniter.methods.noLimit(); // Disables the HTTP limiter
 
 const MEMORY_MODE = true;
 const CURRENCY_NAME = 'duniter_unit_test_currency';
@@ -125,7 +128,7 @@ module.exports = {
       const fakeServer = yield network.createServersAndListen("Fake Duniter Server", [{
         ip: host,
         port: port
-      }], NO_HTTP_LOGS, NO_STATIC_PATH, (app, httpMethods) => {
+      }], NO_HTTP_LOGS, logger, NO_STATIC_PATH, (app, httpMethods) => {
 
         // Mock BMA method for sync mocking
         httpMethods.httpGET('/network/peering', () => {
diff --git a/test/integration/transactions-chaining.js b/test/integration/transactions-chaining.js
index 6412fde9e..de951f884 100644
--- a/test/integration/transactions-chaining.js
+++ b/test/integration/transactions-chaining.js
@@ -5,15 +5,12 @@ const _ = require('underscore');
 const should = require('should');
 const assert = require('assert');
 const constants = require('../../app/lib/constants');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const toolbox   = require('./tools/toolbox');
 const node   = require('./tools/node');
 const user   = require('./tools/user');
 const unit   = require('./tools/unit');
 const http   = require('./tools/http');
-const limiter = require('../../app/lib/system/limiter');
-
-limiter.noLimit();
 
 describe("Transaction chaining", function() {
 
diff --git a/test/integration/transactions-test.js b/test/integration/transactions-test.js
index 70d386a59..e435fbd12 100644
--- a/test/integration/transactions-test.js
+++ b/test/integration/transactions-test.js
@@ -5,15 +5,13 @@ const _ = require('underscore');
 const should = require('should');
 const assert = require('assert');
 const constants = require('../../app/lib/constants');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const toolbox   = require('./tools/toolbox');
 const node   = require('./tools/node');
 const user   = require('./tools/user');
 const unit   = require('./tools/unit');
 const http   = require('./tools/http');
-const limiter = require('../../app/lib/system/limiter');
 
-limiter.noLimit();
 
 describe("Testing transactions", function() {
 
diff --git a/test/integration/v0.4-dividend.js b/test/integration/v0.4-dividend.js
index fa2b22b89..4cd821459 100644
--- a/test/integration/v0.4-dividend.js
+++ b/test/integration/v0.4-dividend.js
@@ -2,7 +2,7 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const commit    = require('./tools/commit');
 const toolbox   = require('./tools/toolbox');
diff --git a/test/integration/v0.4-times.js b/test/integration/v0.4-times.js
index b8f9a8969..c9f7cc61f 100644
--- a/test/integration/v0.4-times.js
+++ b/test/integration/v0.4-times.js
@@ -2,7 +2,7 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const commit    = require('./tools/commit');
 const toolbox   = require('./tools/toolbox');
 
diff --git a/test/integration/v0.5-identity-blockstamp.js b/test/integration/v0.5-identity-blockstamp.js
index f861a8b81..3cda20910 100644
--- a/test/integration/v0.5-identity-blockstamp.js
+++ b/test/integration/v0.5-identity-blockstamp.js
@@ -2,9 +2,8 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const constants = require('../../app/lib/constants');
-const limiter   = require('../../app/lib/system/limiter');
 const toolbox   = require('./tools/toolbox');
 
 const conf = {
@@ -20,7 +19,6 @@ describe("Protocol 0.5 Identity blockstamp", function() {
 
   before(() => co(function*() {
 
-    limiter.noLimit();
     const res1 = yield toolbox.simpleNodeWith2Users(conf);
     const res2 = yield toolbox.simpleNodeWith2otherUsers(conf);
     s1 = res1.s1;
diff --git a/test/integration/v0.5-transactions.js b/test/integration/v0.5-transactions.js
index edbf382af..9a3ac5916 100644
--- a/test/integration/v0.5-transactions.js
+++ b/test/integration/v0.5-transactions.js
@@ -2,9 +2,8 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const constants = require('../../app/lib/constants');
-const limiter   = require('../../app/lib/system/limiter');
 const toolbox   = require('./tools/toolbox');
 
 const conf = {
@@ -21,7 +20,6 @@ describe("Protocol 0.5 Transaction version", function() {
 
   before(() => co(function*() {
 
-    limiter.noLimit();
     const res1 = yield toolbox.simpleNodeWith2Users(conf);
     s1 = res1.s1;
     const cat = res1.cat;
diff --git a/test/integration/v0.6-difficulties.js b/test/integration/v0.6-difficulties.js
index 6a217d9f9..64f98bef6 100644
--- a/test/integration/v0.6-difficulties.js
+++ b/test/integration/v0.6-difficulties.js
@@ -2,9 +2,8 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const constants = require('../../app/lib/constants');
-const limiter   = require('../../app/lib/system/limiter');
 const toolbox   = require('./tools/toolbox');
 
 const conf = {
@@ -20,7 +19,6 @@ describe("Protocol 0.6 Difficulties", function() {
 
   before(() => co(function*() {
 
-    limiter.noLimit();
     const res = yield toolbox.simpleNetworkOf2NodesAnd2Users(conf);
     s1 = res.s1;
     s2 = res.s2;
diff --git a/test/integration/v1.0-source-garbaging.js b/test/integration/v1.0-source-garbaging.js
index 70cd2e98d..f38410e35 100644
--- a/test/integration/v1.0-source-garbaging.js
+++ b/test/integration/v1.0-source-garbaging.js
@@ -2,9 +2,8 @@
 
 const co        = require('co');
 const should    = require('should');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const constants = require('../../app/lib/constants');
-const limiter   = require('../../app/lib/system/limiter');
 const toolbox   = require('./tools/toolbox');
 
 const conf = {
@@ -36,7 +35,6 @@ describe("Protocol 1.0 Source Garbaging", function() {
 
   before(() => co(function*() {
 
-    limiter.noLimit();
     const res1 = yield toolbox.simpleNodeWith2Users(conf);
     s1 = res1.s1;
     cat = res1.cat; // HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd
diff --git a/test/integration/wotb.js b/test/integration/wotb.js
index ce3e35e2e..98581d58d 100644
--- a/test/integration/wotb.js
+++ b/test/integration/wotb.js
@@ -4,7 +4,7 @@ const co        = require('co');
 const should    = require('should');
 const _         = require('underscore');
 const duniter     = require('../../index');
-const bma       = require('../../app/lib/streams/bma');
+const bma       = require('duniter-bma').duniter.methods.bma;
 const user      = require('./tools/user');
 const commit    = require('./tools/commit');
 
-- 
GitLab