diff --git a/config.json b/config.json index e4a1ba7..8b7244d 100644 --- a/config.json +++ b/config.json @@ -8,6 +8,7 @@ "patch": true, "patchBlocks": 100, "bulkSize": 100, + "CMC_API_KEY": "", "settings": { "symbol": "CLO", "name": "Callisto Network", @@ -46,7 +47,7 @@ "0x458ddc6a7e924554756f95715a53bf948560ee38": "clo.digipools.org", "0x3c6b9edb1f8ec6c85436b7cb384eb607489c732f": "vvpool.com", "0x2a1efdf9f09869a82e5e6b0f3736aabcb5381206": "uleypool.com", - "0xf30a30315d5214e490458d0511595e42b3d917d0": "clopool.maxhash.org" + "0xf30a30315d5214e490458d0511595e42b3d917d0": "maxhash.org" } } } diff --git a/db.js b/db.js index 20c0f03..c4e3fcf 100644 --- a/db.js +++ b/db.js @@ -77,6 +77,13 @@ var BlockStat = new Schema( "uncleCount": Number }); +var Market = new Schema({ + "symbol": String, + "timestamp": Number, + "quoteBTC": Number, + "quoteUSD": Number +}) + // create indices Transaction.index({timestamp:-1}); Transaction.index({blockNumber:-1}); @@ -86,17 +93,20 @@ Transaction.index({creates:1, blockNumber:-1}); Account.index({balance:-1}); Account.index({balance:-1, blockNumber:-1}); Block.index({miner:1}); +Market.index({timestamp: -1}) mongoose.model('BlockStat', BlockStat); mongoose.model('Block', Block); mongoose.model('Account', Account); mongoose.model('Contract', Contract); mongoose.model('Transaction', Transaction); +mongoose.model('Market', Market); module.exports.BlockStat = mongoose.model('BlockStat'); module.exports.Block = mongoose.model('Block'); module.exports.Contract = mongoose.model('Contract'); module.exports.Transaction = mongoose.model('Transaction'); module.exports.Account = mongoose.model('Account'); +module.exports.Market = mongoose.model('Market'); mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/blockDB'); diff --git a/package.json b/package.json index 53c0ff1..2e578d4 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "express": "^4.16.0", "mongoose": "^4.10.8", "morgan": "^1.9.0", + "node-fetch": "^2.3.0", "rlp": "^2.0.0", "serve-favicon": "~2.4.5", "socket.io": "^2.0.4", diff --git a/public/css/custom.css b/public/css/custom.css index ab84436..c84b9c2 100755 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -35,7 +35,11 @@ img.logo-default { color: #7f90a4; } .eth-stat-title { - font-size: 25px; + font-size: 20px; + text-align: center; +} +.eth-stat-subtitle { + font-size: 14px; text-align: center; } .eth-stat-text { diff --git a/public/views/address.html b/public/views/address.html index 4781113..89bd622 100644 --- a/public/views/address.html +++ b/public/views/address.html @@ -6,17 +6,14 @@
-
+
- - {{ addr.balance | number: 10 }}
+ {{ addr.balance | number: 4 }} {{ settings.symbol }}
{{ settings.symbol }} Balance -
-
- {{ addr.ethfiat | number: 10 }} ETH-F balance - -
+

+ {{ addr.balanceUSD | currency : "$" : 4 }} USD balance +
{{ addr.mined }} Mined
diff --git a/public/views/simple-summary-stats.html b/public/views/simple-summary-stats.html index 6adf3e6..4f4f043 100644 --- a/public/views/simple-summary-stats.html +++ b/public/views/simple-summary-stats.html @@ -37,7 +37,7 @@

Network Hashrate

- +
{{stats.hashrate | totalDifficulty}}/s

diff --git a/public/views/tx.html b/public/views/tx.html index 71f5023..c8a70a0 100644 --- a/public/views/tx.html +++ b/public/views/tx.html @@ -17,29 +17,36 @@
- - + - - + + - - + + - + - - + + - - - - - - + + + + + + +
Hash{{tx.hash}}
Status +
Transaction Hash:{{tx.hash}}
Status:
Success
Failed
Block Number{{tx.blockNumber}}
Block Number:{{tx.blockNumber}} + + +
Time{{tx.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }} ({{tx.timestamp | timeDuration}} ago)
TimeStamp: {{tx.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }} ({{tx.timestamp | timeDuration}} ago)
From
From: {{tx.from}}
ToContract {{tx.to}}
CreatesContract:{{tx.to}}
Creates: {{tx.creates}}
Value{{tx.value}} {{ settings.symbol }}
Gas Provided{{tx.gas | number}}
Gas Used{{tx.gasUsed | number}}
Gas Price{{tx.gasPrice | number}} wei
Nonce{{tx.nonce}}
Input Data
{{tx.input}}
Value: {{tx.value | number: 4}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }}
Transaction fee:{{tx.transactionFee | number:6}} {{ settings.symbol }} => {{ tx.transactionFeeUSD | currency : "USD $" : 10 }}
Gas Provided:{{tx.gas | number}}
Gas Used:{{tx.gasUsed | number}}
Gas Price:{{tx.gasPrice | number:9}} {{ settings.symbol }} ({{tx.gasPriceGwei | number}} Gwei)
Nonce:{{tx.nonce}}
Input Data:
{{tx.input}}
diff --git a/routes/web3relay.js b/routes/web3relay.js index 3b6edc1..f833a28 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -14,10 +14,11 @@ var asyncL = require('async'); var abiDecoder = require('abi-decoder'); require( '../db.js' ); -var mongoose = require( 'mongoose' ); -var Block = mongoose.model( 'Block' ); -var Contract = mongoose.model( 'Contract' ); -var Transaction = mongoose.model( 'Transaction' ); +const mongoose = require( 'mongoose' ); +const Block = mongoose.model( 'Block' ); +const Contract = mongoose.model( 'Contract' ); +const Transaction = mongoose.model( 'Transaction' ); +const Market = mongoose.model( 'Market' ); var getLatestBlocks = require('./index').getLatestBlocks; var filterBlocks = require('./filters').filterBlocks; @@ -88,7 +89,7 @@ exports.data = async (req, res) => { if ("tx" in req.body) { var txHash = req.body.tx.toLowerCase(); - Transaction.findOne({hash: txHash}).lean(true).exec(function(err, doc) { + Transaction.findOne({hash: txHash}).lean(true).exec(async(err, doc) => { if (err || !doc) { web3.eth.getTransaction(txHash, function(err, tx) { if(err || !tx) { @@ -116,15 +117,27 @@ exports.data = async (req, res) => { if (!err && block) ttx.timestamp = block.timestamp; ttx.isTrace = (ttx.input != "0x"); - res.write(JSON.stringify(ttx)); - res.end(); + transactionResponse = ttx; }); } }); } else { - res.write(JSON.stringify(doc)); - res.end(); + transactionResponse = doc; } + + const latestPrice = await Market.findOne().sort({timestamp: -1}) + + const latestBlock = await web3.eth.getBlockNumber(); + + transactionResponse.confirmations = latestBlock - transactionResponse.blockNumber; + transactionResponse.gasPriceGwei = web3.utils.fromWei(transactionResponse.gasPrice, 'Gwei'); + transactionResponse.gasPrice = web3.utils.fromWei(transactionResponse.gasPrice, 'ether'); + transactionResponse.transactionFee = transactionResponse.gasPrice * transactionResponse.gasUsed; + transactionResponse.transactionFeeUSD = transactionResponse.transactionFee * latestPrice.quoteUSD; + transactionResponse.valueUSD = transactionResponse.value * latestPrice.quoteUSD; + + res.write(JSON.stringify(transactionResponse)); + res.end(); }); } else if ("tx_trace" in req.body) { @@ -469,6 +482,9 @@ exports.data = async (req, res) => { // } } + const latestPrice = await Market.findOne().sort({timestamp: -1}) + addrData["balanceUSD"] = addrData.balance * latestPrice.quoteUSD; + res.write(JSON.stringify(addrData)); res.end(); } else if ("block" in req.body) { diff --git a/tools/price.js b/tools/price.js new file mode 100644 index 0000000..5231635 --- /dev/null +++ b/tools/price.js @@ -0,0 +1,64 @@ +const _ = require('lodash'); +const mongoose = require( 'mongoose' ); +const fetch = require("node-fetch"); +const https = require('https'); +const Market = require( '../db.js' ).Market; + +// 10 minutes +const quoteInterval = 10 * 60 * 1000; + +const getQuote = async () => { + const options = { + timeout: 10000 + } + const URL = `https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=${config.settings.symbol}&CMC_PRO_API_KEY=${config.CMC_API_KEY}`; + + try { + let requestUSD = await fetch(URL); + let requestBTC = await fetch(URL + '&convert=BTC'); + let quoteUSD = await requestUSD.json(); + let quoteBTC = await requestBTC.json(); + console.log(quoteUSD) + + quoteObject = { + symbol: config.settings.symbol, + timestamp: Math.round(new Date(quoteUSD.status.timestamp).getTime() / 1000), + quoteBTC: quoteBTC.data.CLO.quote.BTC.price, + quoteUSD: quoteUSD.data.CLO.quote.USD.price, + } + + new Market(quoteObject).save( ( err, market, count ) => { + console.log(market) + if ( typeof err !== 'undefined' && err ) { + process.exit(9); + } else { + console.log('DB successfully written for market quote.'); + } + }); + } catch (error) { + console.log(error); + } +} + + +var config = { nodeAddr: 'localhost', gethPort: 8545, bulkSize: 100 }; +try { + var local = require('../config.json'); + _.extend(config, local); + console.log('config.json found.'); +} catch (error) { + if (error.code === 'MODULE_NOT_FOUND') { + var local = require('../config.example.json'); + _.extend(config, local); + console.log('No config file found. Using default configuration... (config.example.json)'); + } else { + throw error; + process.exit(1); + } +} + +getQuote() + +setInterval(() => { + getQuote() +}, quoteInterval); \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs index 5914630..f0935a8 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -18,6 +18,7 @@ +