diff --git a/bin/MasterDistiller.js b/bin/MasterDistiller.js
index 319fbca08a567427306be988a225b0123c24dbff..1fcabecc2becf1f6e8215fe7f3ee419f9b29e263 100755
--- a/bin/MasterDistiller.js
+++ b/bin/MasterDistiller.js
@@ -1,18 +1,14 @@
 #!/usr/bin/node
 
 const   Libbfa      =   require( process.env.BFAHOME + '/bin/libbfa.js');
-const   rl          =   require('readline').createInterface( { input: process.stdin, output: process.stdout } );
+const   rl          =   require('readline').createInterface(
+        { input: process.stdin, output: process.stdout }
+    );
 var     web3;
 var     Distillery;
 var     bfa;
 var     notation    =   [ 6 ];
 
-function    fatal( txt )
-{
-    console.log( txt );
-    process.exit( 1 );
-}
-
 function    init()
 {
     notation.push( 10**notation[0] );
@@ -34,18 +30,10 @@ function    init()
             Distillery.contractbalance = val;
             getlist();
         },
-        function err(x){ console.log("Can't do that: "+x);process.exit(1); }
+        function err(x){ bfa.fatal("Can't do that: "+x);process.exit(1); }
     );
 }
 
-function    isNumeric(n) {
-    return !isNaN(parseFloat(n)) && isFinite(n);
-}
-
-function    isAddr(n) {
-    return n.length == 42 && n.substring(0,2) == "0x";
-}
-
 function    palletSort(a,b)
 {
     if ( b == undefined )
@@ -77,10 +65,8 @@ function    requestBalances( count )
         proms.push(
             Distillery.methods.atPosition(i).call( {} )
                 .then(
-                    function(res){
-                        pallet.push(res);
-                    },
-                    function(err) { console.log("Fetching position data failed: "+err) }
+                    function(res) { pallet.push(res); },
+                    function(err) { bfa.fatal("Fetching position data failed: "+err) }
                 )
         );
     }
@@ -95,11 +81,11 @@ function    requestBalances( count )
                 p2.push( web3.eth.getBalance( pallet[i][0] ).then(cb) );
             }
             Promise.all( p2 ).then(
-                function allbalances(a) { displayBalances( pallet ) },
-                function(err) { console.log("Getting balances failed: "+err) }
+                function allbalances(a) { displayBalances(pallet) },
+                function(err) { bfa.fatal("Getting balances failed: "+err) }
             );
         },
-        function(err) { console.log("Getting account list failed: "+err) }
+        function(err) { bfa.fatal("Getting account list failed: "+err) }
     );
 }
 
@@ -115,25 +101,25 @@ function    editAccount( entry, pallet )
     var     acct;
     var     value;
     // it is an existing account address?
-    if ( isAddr(entry) )
+    if ( bfa.isAddr(entry) )
     {
         var     i       =   0;
         var     n       =   pallet.length;
         while ( i < n )
         {
-            if ( (""+pallet[i][0]).toLowerCase() == (""+entry).toLowerCase() )
+            if (String(pallet[i][0]).toLowerCase() == String(entry).toLowerCase() )
                 entry   =   i;
             i++;
         }
     }
     // it is a new account address?
-    if ( isAddr(entry) )
+    if ( bfa.isAddr(entry) )
     {
         acct            =   entry;
         value           =   0;
     }
     else
-    if  ( isNumeric(entry) && entry < pallet.length )
+    if  ( bfa.isNumeric(entry) && entry < pallet.length )
     {
         acct            =   pallet[entry][0];
         value           =   pallet[entry][1];
@@ -155,7 +141,7 @@ function    editAccount( entry, pallet )
                 getlist();
             },
             function distFail(x) {
-                console.log(
+                bfa.fatal(
                     "Distribute returned errors in block# "
                     + x.blockNumber
                     + " using "
@@ -169,42 +155,52 @@ function    editAccount( entry, pallet )
         return;
     }
     else
-        fatal("I don't know what to do with \""+entry+"\"." );
-    rl.question("Adjust the "+notation[2]+" fill value of "+acct+" (setting to 0 is the same as deleting)\nAmount?: ", (answer) => {
-        if ( isNumeric(answer) )
-        {
-            answer      *=  notation[1];
-            console.log("Sending update to the SC...");
-            Distillery.methods.setEtherAllowance(acct,answer).send( {"from": bfa.account } )
-            .then(
-                function(a){
-                    console.log("Update accepted.")
-                    getlist();
-                },
-                function(b){
-                    fatal("\nMaybe you are not authorized:\n"+b+"\n\n\nI think you should leave now.\n");
-                }
-            )
-            ;
+        bfa.fatal("I don't know what to do with \""+entry+"\"." );
+    rl.question(
+        "Adjust the "
+        + notation[2]
+        + " fill value of "
+        + acct
+        + " (setting to 0 is the same as deleting)\n"
+        + "Amount?: ",
+        (answer) => {
+            if ( bfa.isNumeric(answer) )
+            {
+                answer      *=  notation[1];
+                console.log("Sending update to the SC...");
+                Distillery.methods.setEtherAllowance(acct,answer)
+                .send( {"from": bfa.account } )
+                .then(
+                    function(a){
+                        console.log("Update accepted.")
+                        getlist();
+                    },
+                    function(b){
+                        bfa.fatal(
+                            "\nMaybe you are not authorized:\n"
+                            +b
+                            +"\n\n\nI think you should leave now.\n"
+                        );
+                    }
+                )
+            }
+            else
+                bfa.fatal( "I have no idea what to do with \""+answer+"\"." );
+            rl.close;
         }
-        else
-            fatal( "I have no idea what to do with \""+answer+"\"." );
-        rl.close;
-    });
+    );
 }
 
 function    displayBalances( pallet )
 {
     var     n       =   pallet.length;
     var     i;
-    if ( pallet == undefined )
-        fatal( "Bank is not defined." );
     pallet.sort(palletSort);
     console.log(
         "The contract's account ("
         + Distillery.contractaddress
         + ") has "
-        + Math.floor(Distillery.contractbalance/notation[1]).toFixed(notation[0])
+        + Math.floor(Distillery.contractbalance/notation[1]).toFixed(0)
         + " "
         + notation[2]
         + ".\n"
@@ -245,7 +241,7 @@ function    displayBalances( pallet )
         (answer) => {
             if ( answer != undefined )
             {
-                if ( (""+answer).toUpperCase() == 'Q' )
+                if ( String(answer).toUpperCase() == 'Q' )
                     process.exit( 0 );
                 else
                     editAccount(answer, pallet);
@@ -261,7 +257,7 @@ function    getlist()
     .call()
     .then(
         requestBalances,
-        function beneficiaryFail(x){console.log(x)}
+        function beneficiaryFail(x){bfa.fatal(x)}
     );
 }
 
diff --git a/bin/libbfa.js b/bin/libbfa.js
new file mode 100644
index 0000000000000000000000000000000000000000..4af1f4172993f9c9531d5fb07ae92c9591ee299f
--- /dev/null
+++ b/bin/libbfa.js
@@ -0,0 +1,161 @@
+// 20180724 Robert Martin-Legene <robert@nic.ar>
+
+module.exports = class Libbfa
+{
+    constructor() {
+        this.fs                     =   require('fs');
+        this.Web3                   =   require('web3');
+        this._account();
+    }
+
+    fatal( txt )
+    {
+        console.log( txt );
+        process.exit( 1 );
+    }
+
+    _home()
+    {
+        if ( this.home != undefined )
+            return;
+        if ( process.env.BFAHOME == undefined )
+            fatal( "$BFAHOME not set. Did you source bfa/bin/env ?" );
+        this.home                   =   process.env.BFAHOME;
+    }
+
+    _getnetworkid()
+    {
+        if ( this.networkid != undefined )
+            return;
+        this._home();
+        if ( process.env.BFANETWORKID == undefined )
+        {
+            var     netw            =   new Array();
+            this.fs.readdirSync( this.home ).forEach( function(file){
+                if ( file.startWith('network') )
+                    netw.push( 0 + file.substring(7) );
+            });
+            if ( netw.length == 0 )
+                fatal( "Can't determine your network ID." );
+            netw.sort();
+            process.env.BFANETWORKID=
+            this.networkid          =   netw[0];
+        }
+        else
+            this.networkid          =   process.env.BFANETWORKID;
+    }
+
+    _networkdir()
+    {
+        if ( this.networkdir != undefined )
+            return;
+        this._getnetworkid();
+        if ( process.env.BFANETWORKDIR == undefined )
+            process.env.BFANETWORKDIR   =
+                this.networkdir     =   process.env.BFAHOME + '/network' + process.env.BFANETWORKID;
+        else
+            this.networkdir         =   process.env.BFANETWORKDIR;
+    }
+
+    _nodedir()
+    {
+        if ( this.nodedir != undefined )
+            return;
+        this._networkdir();
+        if ( this.networkdir == undefined )
+            return;
+        if ( process.env.BFANODEDIR == undefined )
+        {
+            var     dirs            =   new Array();
+            //var     fs              =   this.fs;
+            var     nwdir           =   this.networkdir;
+            this.fs.readdirSync( this.networkdir ).forEach(
+                function findnodedirs(f1) {
+                    var name1       =   [nwdir,f1].join('/');
+                    var fs          =   require('fs');
+                    if ( fs.statSync( name1 ).isDirectory() )
+                    {
+                        fs.readdirSync( name1 ).forEach(
+                            function lookforkeystores(f2) {
+                                var name2   =   [nwdir,f1,f2].join('/');
+                                if (f2 == "keystore" && fs.statSync( name2 ).isDirectory() )
+                                {
+                                    dirs.push( name1 );
+                                }
+                            }
+                        )
+                    }
+                }
+            );
+            if ( dirs.length == 0 )
+                return;
+            dirs.sort();
+            process.env.BFANODEDIR  =
+                this.nodedir        =   dirs[0];
+        }
+        else
+            this.nodedir            =   process.env.BFANODEDIR;
+        this.netport                =   Number.parseInt( this.fs.readFileSync( this.nodedir + '/netport' ) );
+        this.rpcport                =   Number.parseInt( this.fs.readFileSync( this.nodedir + '/rpcport' ) );
+    }
+
+    _account()
+    {
+        this._nodedir();
+        if ( this.acct != undefined )
+            return;
+        if ( process.env.BFANODEDIR == undefined )
+            return;
+        var     files               =   new Array();
+        this.fs.readdirSync( process.env.BFANODEDIR + '/keystore' ).forEach( function(filename) {
+            if ( filename.includes('--') )
+                files.push( filename );
+        });
+        // found none?
+        if ( files.length == 0 )
+            return;
+        files.sort();
+        this.account                =   '0x' + files[0].replace( /^.*--/, '' );
+    }
+
+    contract(w3, name)
+    {
+        this._networkdir();
+        var     contractdir         =   [ this.networkdir, 'contracts', name ].join('/');
+        var     contractaddress     =   this.fs.realpathSync( contractdir ).replace(/^.*\//, '');
+        if ( contractaddress == undefined )
+            return;
+        var     abi                 =   JSON.parse(
+            this.fs.readFileSync( contractdir + '/abi' ).toString()
+        );
+        if ( abi == undefined )
+            return;
+        var     c                   =   new w3.eth.Contract( abi, contractaddress );
+        c.abi                       =   abi;
+        c.contractaddress           =   contractaddress;
+        return c;
+    }
+
+    newweb3()
+    {
+        this._nodedir();
+        var     provider            =   'http://127.0.0.1:' + this.rpcport;
+        var     w3                  =   new this.Web3( provider );
+        w3.eth.extend({
+            //property: 'bfaclique',
+            methods: [{
+                name: 'getSigners',
+                call: 'clique_getSigners',
+                params: 0
+            }]
+        });
+        return w3;
+    }
+    isNumeric(n) {
+        return !isNaN(parseFloat(n)) && isFinite(n);
+    }
+
+    isAddr(n) {
+        return n.length == 42 && n.substring(0,2) == "0x";
+    }
+}
diff --git a/bin/selfDestructGasWell.sh b/bin/selfDestructGasWell.sh
deleted file mode 100755
index 462305e8af671dfe0ff64e0318ca63265417a61c..0000000000000000000000000000000000000000
--- a/bin/selfDestructGasWell.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-if [ -z "${BFAHOME}" ]; then echo "\$BFAHOME not set. Did you source bfa/bin/env ?" >&2; exit 1; fi
-source ${BFAHOME}/bin/libbfa.sh || exit 1
-
-bfaconfig network
-contract="${BFANETWORKDIR}/contracts/GasWell"
-realdir=$(  realpath "${contract}"      )
-test    -r "${realdir}"
-address=$(  basename "${realdir}"       )
-test    -n "${address}"
-
-contractSendTx GasWell selfDestruct | tee /dev/tty | geth_attach
diff --git a/bin/triggerGasWell.sh b/bin/triggerGasWell.sh
deleted file mode 100755
index a05234d90681d2a9e0712bbd5e44eb0fc646c213..0000000000000000000000000000000000000000
--- a/bin/triggerGasWell.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-if [ -z "${BFAHOME}" ]; then echo "\$BFAHOME not set. Did you source bfa/bin/env ?" >&2; exit 1; fi
-source ${BFAHOME}/bin/libbfa.sh || exit 1
-
-bfaconfig network
-contract="${BFANETWORKDIR}/contracts/GasWell"
-realdir=$(  realpath "${contract}"      )
-test    -r "${realdir}"
-address=$(  basename "${realdir}"       )
-test    -n "${address}"
-
-contractSendTx GasWell distribute | tee /dev/tty | geth_attach