diff --git a/README.md b/README.md index aff3276..58e27ff 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,16 @@ Ethereum Network Intelligence API This is the backend service which runs along with the node for tracking the ethereum network status, fetches information through the JSON-RPC and connects through WebSockets to [eth-netstats](https://github.com/cubedro/eth-netstats) and feed information constantly. ## Prerequisite -* cpp-ethereum +* eth or geth * node * npm ## Installation on Ubuntu -Fetch and run the build shell. This will install everything you need: latest cpp-ethereum - CLI (develop branch), node.js, npm, pm2. +Fetch and run the build shell. This will install everything you need: latest ethereum - CLI from develop branch (you can choose between eth or geth), node.js, npm & pm2. -``` +```bash bash <(curl https://raw.githubusercontent.com/cubedro/eth-net-intelligence-api/master/bin/build.sh) ``` @@ -22,15 +22,15 @@ bash <(curl https://raw.githubusercontent.com/cubedro/eth-net-intelligence-api/m Configure the app modifying [processes.json](/eth-net-intelligence-api/blob/master/processes.json). Note that you have to modify the backup processes.json file located in `./bin/processes.json` (to allow you to set your env vars without being rewritten when updating). -``` +```json "env": { - "NODE_ENV" : "production", // tell the client we're in production environment - "RPC_HOST" : "localhost", // eth JSON-RPC host - "RPC_PORT" : "8080", // eth JSON-RPC port - "INSTANCE_NAME" : "", - "WS_SERVER" : "", // path to eth-netstats WebSockets api server - "WS_SECRET" : "", // WebSockets api server secret used for login + "NODE_ENV" : "production", // tell the client we're in production environment + "RPC_HOST" : "localhost", // eth JSON-RPC host + "RPC_PORT" : "8080", // eth JSON-RPC port + "INSTANCE_NAME" : "", + "WS_SERVER" : "", // path to eth-netstats WebSockets api server + "WS_SECRET" : "", // WebSockets api server secret used for login } ``` @@ -38,7 +38,7 @@ Configure the app modifying [processes.json](/eth-net-intelligence-api/blob/mast Run it using pm2: -``` +```bash cd ~/bin pm2 start processes.json ``` @@ -47,7 +47,7 @@ pm2 start processes.json To update the API client use the following commands: -``` +```bash pm2 kill cd ~/bin/www git pull diff --git a/app.js b/app.js index 47018a6..e8cc01a 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,5 @@ var sleep = require('sleep'); -sleep.sleep(15); +// sleep.sleep(15); var nodeModel = require('./lib/node'); diff --git a/lib/node.js b/lib/node.js index 83c676a..0f01ec0 100644 --- a/lib/node.js +++ b/lib/node.js @@ -3,6 +3,7 @@ var _ = require('lodash'); var os = require('os'); var shelljs = require('shelljs'); var debounce = require('debounce'); +var registrar = require('./registrar.js'); var Primus = require('primus'), Emitter = require('primus-emit'), @@ -14,6 +15,8 @@ var ETH_VERSION, API_VERSION; var INSTANCE_NAME = process.env.INSTANCE_NAME; +var Contract = null; + web3.setProvider(new web3.providers.HttpProvider('http://' + (process.env.RPC_HOST || 'localhost') + ':' + (process.env.RPC_PORT || '8080'))); Socket = Primus.createSocket({ @@ -90,6 +93,9 @@ function Node() this.blocks = []; + this._Registrar = null; + this._knownMiners = []; + this._socket = null; this.pendingFilter = false; this.chainFilter = false; @@ -300,8 +306,31 @@ Node.prototype.gasSpendingChart = function() }); } +Node.prototype.getMinerName = function(miner) +{ + var result = _.find(this._knownMiners, {miner: miner}); + + if(result !== undefined) + { + return result.name; + } + else + { + var name = this._Registrar.name(miner); + + if(name.length > 0) + { + this._knownMiners.push({miner: miner, name: name}); + return name; + } + } + + return false; +} + Node.prototype.minersChart = function() { + var self = this; var miners = _.countBy(this.blocks, function(block) { return block.miner; @@ -309,8 +338,10 @@ Node.prototype.minersChart = function() var minersArray = []; - _.forEach(miners, function(cnt, miner) { - minersArray.push({miner: miner, blocks: cnt}); + _.forEach(miners, function(cnt, miner) + { + var name = self.getMinerName(miner); + minersArray.push({miner: miner, name: name, blocks: cnt}); }); var minersArray = _.sortBy(minersArray, 'blocks').reverse(); @@ -437,8 +468,15 @@ Node.prototype.emit = function(message, payload) } } +Node.prototype.installContract = function() +{ + Contract = web3.eth.contract(registrar.desc); + this._Registrar = new Contract(registrar.address); +} + Node.prototype.init = function() { + this.installContract(); this.update(); this.setWatches(); } @@ -458,4 +496,33 @@ Node.prototype.stop = function() web3.reset(); } +function directICAP(address) +{ + if (address[0] != 0) + return ''; + + var d = toBase36(address); + + while(d.length < 30) + d = "0" + d; + + return d; + // return iban("XE", d); +} + +function toBase36(hex) +{ + var c_alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + var a = hex.length; + var ret = ''; + + for(; a > 0; a = a/36){ + ret = c_alphabet[a%36] + ret; + console.log('a: ', a); + console.log('ret: ', ret); + } + + return ret; +} + module.exports = Node; \ No newline at end of file diff --git a/lib/registrar.js b/lib/registrar.js new file mode 100644 index 0000000..df0eb46 --- /dev/null +++ b/lib/registrar.js @@ -0,0 +1,169 @@ +var address = "0xc6d9d2cd449a754c494264e1809c50e34d64562b"; +var registrar = [ + { + "constant":true, + "inputs": + [ + { + "name":"_owner", + "type":"address" + } + ], + "name":"name", + "outputs": + [ + { + "name":"o_name", + "type":"bytes32" + } + ], + "type":"function" + }, + { + "constant":true, + "inputs": + [ + { + "name":"_name", + "type":"bytes32" + } + ], + "name":"owner", + "outputs": + [ + { + "name":"o_owner", + "type":"address" + } + ], + "type":"function" + }, + { + "constant":true, + "inputs": + [ + { + "name":"_name", + "type":"bytes32" + } + ], + "name":"getAddress", + "outputs": + [ + { + "name":"o_owner", + "type":"address" + } + ], + "type":"function" + }, + { + "constant":true, + "inputs": + [ + { + "name":"_name", + "type":"bytes32" + } + ], + "name":"content", + "outputs": + [ + { + "name":"o_content", + "type":"bytes32" + } + ], + "type":"function" + }, + { + "constant":true, + "inputs": + [ + { + "name":"_name", + "type":"bytes32" + } + ], + "name":"addr", + "outputs": + [ + { + "name":"o_address", + "type":"address" + } + ], + "type":"function" + }, + { + "constant":true, + "inputs": + [ + { + "name":"_name", + "type":"bytes32" + } + ], + "name":"subRegistrar", + "outputs": + [ + { + "name":"o_subRegistrar", + "type":"address" + } + ], + "type":"function" + }, + { + "constant":true, + "inputs": + [ + { + "name":"_owner", + "type":"address" + } + ], + "name":"getName", + "outputs": + [ + { + "name":"o_name", + "type":"bytes32" + } + ], + "type":"function" + }, + { + "anonymous":false, + "inputs": + [ + { + "indexed":true, + "name":"name", + "type":"bytes32" + } + ], + "name":"Changed", + "type":"event" + }, + { + "anonymous":false, + "inputs": + [ + { + "indexed":true, + "name":"name", + "type":"bytes32" + }, + { + "indexed":true, + "name":"addr", + "type":"address" + } + ], + "name":"PrimaryChanged", + "type":"event" + } +]; + +module.exports = { desc: registrar, address: address}; \ No newline at end of file