From 5fb7eafd15f2988644754746e0a2a9a385b761ac Mon Sep 17 00:00:00 2001 From: Cody Burns Date: Sun, 9 Dec 2018 02:29:31 -0600 Subject: [PATCH 01/46] org update ethereumproject >> ethereumclassic --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e40443eb2..f5b62e22a 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ Live Version: [etherhub.io](http://etherhub.io) -Follow the project progress at: [ETC Block Explorer Development](https://github.com/ethereumproject/explorer) +Follow the project progress at: [ETC Block Explorer Development](https://github.com/ethereumclassic/explorer) ## Local installation Clone the repo -`git clone https://github.com/ethereumproject/explorer` +`git clone https://github.com/ethereumclassic/explorer` Download [Nodejs and npm](https://docs.npmjs.com/getting-started/installing-node "Nodejs install") if you don't have them @@ -79,4 +79,4 @@ Enabling stats requires running a separate process: `node ./tools/stats.js` You can configure intervals (how often a new data point is pulled) and range (how many blocks to go back) with the following: -`RESCAN=1000:100000 node tools/stats.js` (New data point every 1,000 blocks. Go back 100,000 blocks). \ No newline at end of file +`RESCAN=1000:100000 node tools/stats.js` (New data point every 1,000 blocks. Go back 100,000 blocks). From a0ef5330f7de6c3617c2c37d5861eaed28d0a92a Mon Sep 17 00:00:00 2001 From: Kimi Sian-yu Chen Date: Sun, 16 Dec 2018 01:49:38 +0800 Subject: [PATCH 02/46] Change to ethereumclassic --- config.example.json | 2 +- package.json | 2 +- public/tpl/footer.html | 6 +++--- public/tpl/header.html | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config.example.json b/config.example.json index 3a76b9276..916bfc162 100644 --- a/config.example.json +++ b/config.example.json @@ -18,7 +18,7 @@ "reddit": "https://www.reddit.com/r/EthereumClassic", "twitter": "https://twitter.com/eth_classic", "linkedin": "https://www.linkedin.com/company/ethereum-classic", - "github": "https://github.com/ethereumproject", + "github": "https://github.com/ethereumclassic", "logo": "/img/explorer-logo.png", "customCss": "green-haze.min.css", "copyright": "2018 © Ethereum Classic.", diff --git a/package.json b/package.json index ff935bcee..37af2811b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "private": false, "version": "0.2.0", "description": "A lightweight ethereum classic block explorer", - "repository": "https://github.com/ethereumproject/explorer", + "repository": "https://github.com/ethereumclassic/explorer", "license": "MIT", "scripts": { "start": "concurrently \"node tools/sync.js \" \"node app.js\" ", diff --git a/public/tpl/footer.html b/public/tpl/footer.html index c376ec70a..0ca2be55c 100755 --- a/public/tpl/footer.html +++ b/public/tpl/footer.html @@ -6,8 +6,8 @@

About

{{settings.about}}

{{settings.poweredbyCustom}} - -

Powered by ETC Explorer

+ +

Powered by ETC Explorer

@@ -108,7 +94,7 @@ - + diff --git a/public/views/dao.html b/public/views/dao.html index 86abe1cad..dbff97858 100644 --- a/public/views/dao.html +++ b/public/views/dao.html @@ -9,7 +9,7 @@ {{ dao.balance | number: 10 }}
TheDAO Balance -
+
{{ dao.extra_balance | number: 10 }} TheDAO Extra Balance @@ -29,16 +29,9 @@
- - WATCH - WATCHING -
- {{ dao.follow_count }}0 - WATCHING -
@@ -53,7 +46,7 @@
- +
-
\ No newline at end of file +
diff --git a/public/views/token.html b/public/views/token.html index 8a031e57f..ff8f71b27 100644 --- a/public/views/token.html +++ b/public/views/token.html @@ -9,7 +9,7 @@ {{ token.balance | number: 10 }}
{{ token.name }} Address Balance ({{ settings.symbol }}) -
+
{{ token.total_supply | number:1 }} Total {{ token.symbol }} Tokens
@@ -25,16 +25,9 @@
- - WATCH - WATCHING -
- {{ token.follow_count }}0 - WATCHING -
@@ -53,7 +46,7 @@
- +
@@ -113,8 +106,8 @@

You have 0{{userTokens | numb
-
+

-
\ No newline at end of file +
From 7922302c4a4ef1b99fd8a5817ef4adb3854658d7 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:09 +0900 Subject: [PATCH 08/46] cleanup: enforce lowercase on transactions & accounts --- db.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/db.js b/db.js index 178379032..a7a75083a 100644 --- a/db.js +++ b/db.js @@ -12,7 +12,7 @@ var Block = new Schema( "transactionsRoot": String, "stateRoot": String, "receiptRoot": String, - "miner": String, + "miner": {type: String, lowercase: true}, "difficulty": String, "totalDifficulty": String, "size": Number, @@ -46,13 +46,13 @@ var Contract = new Schema( var Transaction = new Schema( { - "hash": {type: String, index: {unique: true}}, + "hash": {type: String, index: {unique: true}, lowercase: true}, "nonce": Number, "blockHash": String, "blockNumber": Number, "transactionIndex": Number, - "from": String, - "to": String, + "from": {type: String, lowercase: true}, + "to": {type: String, lowercase: true}, "value": String, "gas": Number, "gasPrice": String, From 23145e1faf036bb2d552ef66be68a5807922dc99 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:11 +0900 Subject: [PATCH 09/46] cleanup: support mongodb authentication --- README.md | 68 +++++++++++++++++++++++++++++++++++++++++++-- config.example.json | 16 +++++------ db.js | 4 +++ 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index efc1c5837..8da81b3a0 100644 --- a/README.md +++ b/README.md @@ -108,9 +108,71 @@ Basic settings: ```patchBlocks``` If `patch` is set to true, the amount of block specified will be check from the latest one. +### Mongodb Auth setting. -### Run: -The below will start both the web-gui and sync.js (which populates MongoDV with blocks/transactions). +#### Configure MongoDB + +In view of system security, most of mongoDB Admin has setup security options, So, You need to setup mongodb auth informations. +Switch to the built-in admin database: + +``` +$ mongo +$ > use admin +``` + +1. Create an administrative user (if you have already admin or root of mongodb account, then skip it) + +``` +# make admin auth and role setup +$ > db.createUser( { user: "admin", pwd: "", roles: ["root"] } ) +``` + +And, You can make Explorer's "blockDB" database with db user accounts "explorer" and password "some_pass_code". + +``` +$ > use blockDB +$ > db.createUser( { user: "explorer", pwd: "", roles: ["dbOwner"] } ) +$ > quit() +``` + +Above dbuser explorer will full access blockDB and clustor setting will be well used on monitoring the multiple sharding and replication of multiple mongodb instances. +Enable database authorization in the MongoDB configuration file /etc/mongodb.conf by appending the following lines: + +``` +auth=true +``` + +Restart MongoDB and verify the administrative user created earlier can connect: + +``` +$ sudo service mongodb restart +$ mongo -u admin -p your_password --authenticationDatabase=admin +``` + +If everything is configured correctly the Mongo Shell will connect and + +``` +$ > show dbs +``` + +will show db informations. +and You can add modified from ./db.js:103 lines, add auth information and mongodb connect options. + +``` +mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/blockDB', { + useMongoClient: true + // poolSize: 5, + // rs_name: 'myReplicaSetName', + // user: 'explorer', + // pass: 'yourdbpasscode' +}); +``` + +And explore it. + +### Run + +The below will start both the web-gui and sync.js (which populates MongoDB with blocks/transactions). `npm start` You can leave sync.js running without app.js and it will sync and grab blocks based on config.json parameters @@ -120,4 +182,4 @@ Enabling stats requires running a separate process: `node ./tools/stats.js` You can configure intervals (how often a new data point is pulled) and range (how many blocks to go back) with the following: -`RESCAN=100:7400000 node tools/stats.js` (New data point every 100 blocks. Go back 7,400,000 blocks). +`RESCAN=100:7700000 node tools/stats.js` (New data point every 100 blocks. Go back 7,700,000 blocks). diff --git a/config.example.json b/config.example.json index 3a76b9276..3925e043c 100644 --- a/config.example.json +++ b/config.example.json @@ -2,6 +2,7 @@ "nodeAddr": "localhost", "gethPort": 8545, "startBlock": 0, + "endBlock": "latest", "quiet": true, "syncAll": true, "patch": true, @@ -37,22 +38,19 @@ "0x4c2b4e716883a2c3f6b980b70b577e54b9441060": "ETCPool PL", "0xd144e30a0571aaf0d0c050070ac435deba461fab": "Clona Network", "0x568f58bf1667504fdf5aa02d776c156f940178a5": "Whalesburg", - "0x3b2d2613ad66d66ee0cb518aeeccc98e9e3b19c0": "private(0x3b2d2613)", - "0x919973eb38844313dc31c41e140700d6e333f8d5": "private(0x919973eb)", - "0xb205f337bad80e28351c7540b741c81470c4927f": "private(0xb205f337)", - "0x232cad0429e653ab610fbcf7e7ebee2f05f28410": "private(0x232cad04)", "0x999c2944807874d3677ee3c6065c8a8a92721ac5": "NinjaPool.jp", "0x39cd14977601184b7da518fd352261aad0cb9fd3": "91pool", "0xf35074bbd0a9aee46f4ea137971feec024ab704e": "Solo Mining Pools", "0xa97ed75172773ec705c2c78d999d3203199101bd": "epool", - "0x58b3cabd0c5c777da2c1c4d4f7ecc8afe5674f20": "private(0x58b3cabd0)", "0x87cfd09c483fe65352456bb26c784a0e4c4ba389": "ArsMine", - "0x5bc9ccbd3115cefb6f382d33e8ce2a0aba084da4": "private(0x5bc9ccbd3)", - "0x4924414988feb1ee16e29298509f96317400eb57": "private(0x492441498)", - "0xa9a926bed50dc038b20bb20de361e4c35aae51fc": "private(0xa9a926bed)", "0x0073cf1b9230cf3ee8cab1971b8dbef21ea7b595": "2miners", "0x004730417cd2b1d19f6be2679906ded4fa8a64e2": "2miners", - "0x1c0fa194a9d3b44313dcd849f3c6be6ad270a0a4": "MiningPoolHub" + "0x1c0fa194a9d3b44313dcd849f3c6be6ad270a0a4": "MiningPoolHub", + "0x8c5535afdbdeea80adedc955420f684931bf91e0": "MiningPoolHub", + "0xfe0ca4e9d8b83ff2d03ef4f35f0b5f754e81d1fd": "Hiveon Pool", + "0xeda79f0735a56510876a497e1c105916666b0199": "Comining", + "0xd3bfd58a31ddeb2fdd2bc212e38c41725bc93ccd": "EtherDig HVPPS", + "0xf35074bbd0a9aee46f4ea137971feec024ab704e": "solopool.org" } } } diff --git a/db.js b/db.js index a7a75083a..83b922dee 100644 --- a/db.js +++ b/db.js @@ -98,6 +98,10 @@ module.exports.Account = mongoose.model('Account'); mongoose.Promise = global.Promise; mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/blockDB', { useMongoClient: true + // poolSize: 5, + // rs_name: 'myReplicaSetName', + // user: 'explorer', + // pass: 'yourdbpasscode' }); // mongoose.set('debug', true); From 455454bcec11695c8eb3e18a1b65a7231ff12590 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:12 +0900 Subject: [PATCH 10/46] cleanup: update richlist explanation --- README.md | 6 ++++++ config.example.json | 1 + public/tpl/header.html | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8da81b3a0..2bdbd6405 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Basic settings: "patch": true, "patchBlocks": 100, "bulkSize": 100, + "useRichList": true, "settings": { "symbol": "ETC", "name": "Ethereum Classic", @@ -108,6 +109,8 @@ Basic settings: ```patchBlocks``` If `patch` is set to true, the amount of block specified will be check from the latest one. +```useRichList``` If `useRichList` is set to true, explorer will update account balance for richlist page. + ### Mongodb Auth setting. #### Configure MongoDB @@ -181,5 +184,8 @@ You can leave sync.js running without app.js and it will sync and grab blocks ba Enabling stats requires running a separate process: `node ./tools/stats.js` +Enabling richlist requires running a separate process: +`node ./tools/richlist.js` + You can configure intervals (how often a new data point is pulled) and range (how many blocks to go back) with the following: `RESCAN=100:7700000 node tools/stats.js` (New data point every 100 blocks. Go back 7,700,000 blocks). diff --git a/config.example.json b/config.example.json index 3925e043c..b1387a365 100644 --- a/config.example.json +++ b/config.example.json @@ -8,6 +8,7 @@ "patch": true, "patchBlocks": 100, "bulkSize": 100, + "useRichList": true, "settings": { "symbol": "ETC", "name": "Ethereum Classic", diff --git a/public/tpl/header.html b/public/tpl/header.html index faf41ddcd..d4b6fd08c 100755 --- a/public/tpl/header.html +++ b/public/tpl/header.html @@ -44,7 +44,7 @@
  • Home
  • -
  • +
  • Accounts
  • -
  • - - TheDAO -
  • View All Tokens diff --git a/public/views/dao.html b/public/views/dao.html deleted file mode 100644 index dbff97858..000000000 --- a/public/views/dao.html +++ /dev/null @@ -1,92 +0,0 @@ - -
    -
    -
    -
    -
    -
    - - {{ dao.balance | number: 10 }}
    - - TheDAO Balance -
    -
    - {{ dao.extra_balance | number: 10 }} TheDAO Extra Balance - -
    -
    - {{ dao.total_supply | number:1 }} Total Tokens -
    -
    - Token Holders -
    -
    - {{ dao.count }} Transactions -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    - -
    -
    - - -
    -
    - -
    - -
    -
    -

    Get DAO-C Token Balance

    -
    -
    - Enter Your Address -
    - - - - -
    - {{errors.address}} -
    -
    -
    -
    -

    You have 0{{dao.tokens | number}} DAO-C tokens.

    -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    diff --git a/routes/dao.js b/routes/dao.js deleted file mode 100644 index 037ecbd4a..000000000 --- a/routes/dao.js +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env node - -/* - Endpoint for client to talk to node about DAO stuff -*/ - -var eth = require('./web3relay').eth; -require( '../db-dao' ); - -var mongoose = require( 'mongoose' ); -var DAOCreatedToken = mongoose.model('DAOCreatedToken'); -var DAOTransferToken = mongoose.model('DAOTransferToken'); - -var BigNumber = require('bignumber.js'); -var etherUnits = require(__lib + "etherUnits.js") - -var extraBalanceAddr = "0x807640a13483f8ac783c557fcdf27be11ea4ac7a"; -var daoABI = [{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"},{"name":"description","type":"string"},{"name":"votingDeadline","type":"uint256"},{"name":"open","type":"bool"},{"name":"proposalPassed","type":"bool"},{"name":"proposalHash","type":"bytes32"},{"name":"proposalDeposit","type":"uint256"},{"name":"newCurator","type":"bool"},{"name":"yea","type":"uint256"},{"name":"nay","type":"uint256"},{"name":"creator","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"minTokensToCreate","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"rewardAccount","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"daoCreator","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"divisor","outputs":[{"name":"divisor","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"extraBalance","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_proposalID","type":"uint256"},{"name":"_transactionData","type":"bytes"}],"name":"executeProposal","outputs":[{"name":"_success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"unblockMe","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"totalRewardToken","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"actualBalance","outputs":[{"name":"_actualBalance","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"closingTime","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"allowedRecipients","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferWithoutReward","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"refund","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_description","type":"string"},{"name":"_transactionData","type":"bytes"},{"name":"_debatingPeriod","type":"uint256"},{"name":"_newCurator","type":"bool"}],"name":"newProposal","outputs":[{"name":"_proposalID","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"DAOpaidOut","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"minQuorumDivisor","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_newContract","type":"address"}],"name":"newContract","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_allowed","type":"bool"}],"name":"changeAllowedRecipients","outputs":[{"name":"_success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"halveMinQuorum","outputs":[{"name":"_success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"paidOut","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_proposalID","type":"uint256"},{"name":"_newCurator","type":"address"}],"name":"splitDAO","outputs":[{"name":"_success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"DAOrewardAccount","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"proposalDeposit","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"numberOfProposals","outputs":[{"name":"_numberOfProposals","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"lastTimeMinQuorumMet","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_toMembers","type":"bool"}],"name":"retrieveDAOReward","outputs":[{"name":"_success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"receiveEther","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"isFueled","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_tokenHolder","type":"address"}],"name":"createTokenProxy","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"_proposalID","type":"uint256"}],"name":"getNewDAOAddress","outputs":[{"name":"_newDAO","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_proposalID","type":"uint256"},{"name":"_supportsProposal","type":"bool"}],"name":"vote","outputs":[{"name":"_voteID","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"getMyReward","outputs":[{"name":"_success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"rewardToken","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFromWithoutReward","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_proposalDeposit","type":"uint256"}],"name":"changeProposalDeposit","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"blocked","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"curator","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"_proposalID","type":"uint256"},{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_transactionData","type":"bytes"}],"name":"checkProposalCode","outputs":[{"name":"_codeChecksOut","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"privateCreation","outputs":[{"name":"","type":"address"}],"type":"function"},{"inputs":[{"name":"_curator","type":"address"},{"name":"_daoCreator","type":"address"},{"name":"_proposalDeposit","type":"uint256"},{"name":"_minTokensToCreate","type":"uint256"},{"name":"_closingTime","type":"uint256"},{"name":"_privateCreation","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"value","type":"uint256"}],"name":"FuelingToDate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"CreatedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"newCurator","type":"bool"},{"indexed":false,"name":"description","type":"string"}],"name":"ProposalAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"position","type":"bool"},{"indexed":true,"name":"voter","type":"address"}],"name":"Voted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"result","type":"bool"},{"indexed":false,"name":"quorum","type":"uint256"}],"name":"ProposalTallied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_newCurator","type":"address"}],"name":"NewCurator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_recipient","type":"address"},{"indexed":false,"name":"_allowed","type":"bool"}],"name":"AllowedRecipientChanged","type":"event"}] -var daoContract = eth.contract(daoABI); -var DAO = daoContract.at("0xbb9bc244d798123fde783fcc1c72d3bb8c189413"); - -module.exports = function(req, res){ - console.log(req.body) - - if (!("action" in req.body)) - res.status(400).send(); - else if (req.body.action=="info") { - try { - var actualBalance = DAO.actualBalance(); - actualBalance = etherUnits.toEther(actualBalance, 'wei'); - var extraBalance = eth.getBalance(extraBalanceAddr); - extraBalance = etherUnits.toEther(extraBalance, 'wei'); - var totalSupply = DAO.totalSupply(); - totalSupply = etherUnits.toEther(totalSupply, 'wei')*100; - var daoData = { - "balance": actualBalance, - "extra_balance": extraBalance, - "total_supply": totalSupply - } - res.write(JSON.stringify(daoData)); - res.end(); - } catch (e) { - console.error(e); - } - } else if (req.body.action=="balanceOf") { - var addr = req.body.addr.toLowerCase(); - try { - var tokens = DAO.balanceOf(addr); - tokens = etherUnits.toEther(tokens, 'wei')*100; - res.write(JSON.stringify({"tokens": tokens})); - res.end(); - } catch (e) { - console.error(e); - } - } else if (req.body.action=="createdTokens") { - if (req.body.last_id) - var options = {'_id': {$lt: req.body.last_id}}; - else - var options = {}; - var ctFind = DAOCreatedToken.find(options).lean(true).sort('-blockNumber').limit(MAX_ENTRIES); - ctFind.exec(function (err, docs) { - if (!docs.length){ - res.write(JSON.stringify([])); - } else { - var formatDocs = docs.map( function(doc) { - var d = doc; - d.amount = etherUnits.toEther(d.amount, 'wei')*100; - return d; - }); - res.write(JSON.stringify(formatDocs)); - } - res.end(); - }); - } else if (req.body.action=="transferTokens") { - if (req.body.last_id) - var options = {'_id': {$lt: req.body.last_id}}; - else - var options = {}; - var ctFind = DAOTransferToken.find(options).lean(true).sort('-blockNumber').limit(MAX_ENTRIES); - ctFind.exec(function (err, docs) { - if (!docs.length){ - res.write(JSON.stringify([])); - } else { - var formatDocs = docs.map( function(doc) { - var d = doc; - d.amount = etherUnits.toEther(d.amount, 'wei')*100; - return d; - }); - res.write(JSON.stringify(formatDocs)); - } - res.end(); - }); - } - -}; - -const MAX_ENTRIES = 50; \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 46c230147..998eb9bbc 100644 --- a/routes/index.js +++ b/routes/index.js @@ -9,7 +9,6 @@ var async = require('async'); module.exports = function(app){ var web3relay = require('./web3relay'); - var DAO = require('./dao'); var Token = require('./token'); var compile = require('./compiler'); @@ -17,9 +16,9 @@ module.exports = function(app){ var stats = require('./stats'); var richList = require('./richlist'); - /* + /* Local DB: data request format - { "address": "0x1234blah", "txin": true } + { "address": "0x1234blah", "txin": true } { "tx": "0x1234blah" } { "block": "1234" } */ @@ -30,8 +29,7 @@ module.exports = function(app){ app.post('/block', getBlock); app.post('/data', getData); - app.post('/daorelay', DAO); - app.post('/tokenrelay', Token); + app.post('/tokenrelay', Token); app.post('/web3relay', web3relay.data); app.post('/compile', compile); @@ -49,7 +47,7 @@ var getAddr = function(req, res){ var data = { draw: parseInt(req.body.draw), recordsFiltered: count, recordsTotal: count, mined: 0 }; - var addrFind = Transaction.find( { $or: [{"to": addr}, {"from": addr}] }) + var addrFind = Transaction.find( { $or: [{"to": addr}, {"from": addr}] }) var sortOrder = '-blockNumber'; if (req.body.order && req.body.order[0] && req.body.order[0].column) { @@ -151,15 +149,15 @@ var getData = function(req, res){ if (isNaN(limit)) var lim = MAX_ENTRIES; else - var lim = parseInt(limit); + var lim = parseInt(limit); DATA_ACTIONS[action](lim, res); - } else { + } else { console.error("Invalid Request: " + action) res.status(400).send(); } }; -/* +/* temporary blockstats here */ var latestBlock = function(req, res) { @@ -169,7 +167,7 @@ var latestBlock = function(req, res) { res.write(JSON.stringify(doc)); res.end(); }); -} +} var getLatest = function(lim, res, callback) { @@ -227,4 +225,3 @@ const DATA_ACTIONS = { "latest_blocks": sendBlocks, "latest_txs": sendTxs } - diff --git a/tools/tokens/daoTxns.js b/tools/tokens/daoTxns.js deleted file mode 100644 index 3922fcbd6..000000000 --- a/tools/tokens/daoTxns.js +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/env node - -/* - Thing to get history of DAO transactions -*/ - -var Web3 = require("web3"); -var web3; -var async = require('async'); - -require( '../../db.js' ); -require( '../../db-dao.js' ); -require( '../../db-internal.js' ); -var mongoose = require( 'mongoose' ); -var Block = mongoose.model('Block'); -var DAOCreatedToken = mongoose.model('DAOCreatedToken'); -var DAOTransferToken = mongoose.model('DAOTransferToken'); -var InternalTx = mongoose.model( 'InternalTransaction' ); - -// load config.json -var config = { nodeAddr: 'localhost', gethPort: 8545 }; -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); - } -} - -console.log('Connecting ' + config.nodeAddr + ':' + config.gethPort + '...'); - -if (typeof web3 !== "undefined") { - web3 = new Web3(web3.currentProvider); -} else { - web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.gethPort.toString())); -} - -if (web3.isConnected()) - console.log("Web3 connection established"); -else - throw "No connection"; - - -var daoABI = [{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"value","type":"uint256"}],"name":"FuelingToDate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"CreatedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"newCurator","type":"bool"},{"indexed":false,"name":"description","type":"string"}],"name":"ProposalAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"position","type":"bool"},{"indexed":true,"name":"voter","type":"address"}],"name":"Voted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"result","type":"bool"},{"indexed":false,"name":"quorum","type":"uint256"}],"name":"ProposalTallied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_newCurator","type":"address"}],"name":"NewCurator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_recipient","type":"address"},{"indexed":false,"name":"_allowed","type":"bool"}],"name":"AllowedRecipientChanged","type":"event"}]; -var daoContract = web3.eth.contract(daoABI); -var DAO = daoContract.at("0xbb9bc244d798123fde783fcc1c72d3bb8c189413"); - -var creationBlock = 1428757; -var creationEnd = 1599205; - -var populateCreatedTokens = function () { - //total: 58713 - - var event = DAO.CreatedToken; - event({}, {fromBlock: creationBlock, toBlock: creationEnd}).get( function(err, log) { - if (err) { - console.error(err); - process.exit(9); - } else { - for (var l in log) { - try { - var newToken = { - "transactionHash": log[l].transactionHash, - "blockNumber": log[l].blockNumber, - "amount": log[l].args.amount, - "to": log[l].args.to - } - } catch (e) { - console.error(e); - continue; - } - - new DAOCreatedToken(newToken).save( function( err, token, count ){ - if ( typeof err !== 'undefined' && err ) { - if (err.code == 11000) { - console.log('Skip: Duplicate tx ' + - log[l].transactionHash + ': ' + - err); - } else { - console.log('Error: Aborted due to error on ' + - 'block number ' + log[l].blockNumber.toString() + ': ' + - err); - process.exit(9); - } - } else - console.log('DB successfully written for tx ' + - token.transactionHash ); - - }); - } - } - - }); -} - -var populateTransferTokens = function () { - - var event = DAO.Transfer; - event({}, {fromBlock: creationEnd, toBlock: "latest"}).get( function(err, log) { - if (err) { - console.error(err); - process.exit(9); - } else { - for (var l in log) { - try { - var newToken = { - "transactionHash": log[l].transactionHash, - "blockNumber": log[l].blockNumber, - "amount": log[l].args._amount, - "to": log[l].args._to, - "from": log[l].args._from - } - } catch (e) { - console.error(e); - continue; - } - try { - var block = web3.eth.getBlock(log[l].blockNumber); - newToken.timestamp = block.timestamp; - } catch (e) { - console.error(e); - continue; - } - new DAOTransferToken(newToken).save( function( err, token, count ){ - if ( typeof err !== 'undefined' && err ) { - if (err.code == 11000) { - console.log('Skip: Duplicate tx ' + - log[l].transactionHash + ': ' + - err); - return null; - } else { - console.log('Error: Aborted due to error on ' + - 'block number ' + log[l].blockNumber.toString() + ': ' + - err); - process.exit(9); - } - } else - console.log('DB successfully written for tx ' + - log[l].transactionHash ); - - }); - } - } - - }); -} - -var bulkTimeUpdate = function(bulk, callback) { - console.log("Bulk execution started"); - bulk.execute(function(err,result) { - if (err) - console.error(err); - else - console.log(result.toJSON()); - }); -} - - -var patchTimestamps = function(collection) { - mongoose.connection.on("open", function(err,conn) { - - var bulk = collection.initializeOrderedBulkOp(); - - var bulkOps = []; - var count = 0; - var missingCount = 5200; - collection.count({timestamp: null}, function(err, c) { - missingCount = c; - console.log("Missing: " + JSON.stringify(missingCount)); - }); - - collection.find({timestamp: null}).forEach(function(doc) { - setTimeout(function() { - try { - var block = web3.eth.getBlock(doc.blockNumber); - } catch (e) { - console.error(e); return; - } - - bulk.find({ '_id': doc._id }).updateOne({ - '$set': { 'timestamp': block.timestamp } - }); - count++; - if(count % 100 === 0) { - // Execute per 1000 operations and re-init - bulkTimeUpdate(bulk); - bulk = collection.initializeOrderedBulkOp(); - } - if(count == missingCount) { - // Clean up queues - bulkTimeUpdate(bulk); - } - }, 1000); - }); - - }) -} - -const BATCH = 1000; - -var patchBlocks = function(max, min) { - - Block.find({"number": {$gt: min, $lt: max}}, "number timestamp").lean(true).exec(function(err, docs) { - async.forEach(docs, function(doc, cb) { - var q = { 'timestamp': null, 'blockNumber': doc.number }; - InternalTx.collection.update(q, { $set: { 'timestamp': doc.timestamp }}, - {multi: true, upsert: false}, function(err, tx) { - if(err) console.error(err); - console.log(tx) - cb(); - }); - }, function() { return; }); - }); - -} - -InternalTx.collection.count({timestamp: null}, function(err, c) { - missingCount = c; - console.log("Missing: " + JSON.stringify(missingCount)); -}); - -var min; - -var max = web3.eth.blockNumber; - -setInterval(function() { - InternalTx.findOne({"timestamp": null}, "blockNumber") - .lean(true).sort('blockNumber') - .exec(function(err, doc) { - console.log(doc) - if (doc) - min = doc.blockNumber - 1; - else - min = max; - - var next = min + BATCH; - if (next > max) - process.exit(9) - - patchBlocks(next, min); - }); -}, 20000); - - -// patchTimestamps(InternalTx.collection) -// populateCreatedTokens(); -// populateTransferTokens(); From a060bbfdd281e0cfa9e9af38402d2d6711405f7e Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:15 +0900 Subject: [PATCH 12/46] cleanup: drop diff bomb chart support --- .gitignore | 3 +- public/js/controllers/StatsController.js | 974 +---------------------- public/tpl/header.html | 4 - public/views/stats/index.html | 1 - 4 files changed, 5 insertions(+), 977 deletions(-) diff --git a/.gitignore b/.gitignore index 465b204cb..b7e28db57 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,6 @@ jspm_packages # local data data/ package-lock.json -public/js/stats/The_bomb_chart.js config.json .node-xmlhttprequest-* -/nbproject/private/ \ No newline at end of file +/nbproject/private/ diff --git a/public/js/controllers/StatsController.js b/public/js/controllers/StatsController.js index 5fc5b2582..3196d492e 100755 --- a/public/js/controllers/StatsController.js +++ b/public/js/controllers/StatsController.js @@ -2,16 +2,16 @@ angular.module('BlocksApp').controller('StatsController', function($stateParams, $rootScope.isHome = false; $scope.settings = $rootScope.setup; - + /* - Chart types: + Chart types: hashrate: Hashrate Growth miner_hashrate: Miner Hashrate Distribution */ const CHART_TYPES = { "hashrate": { - "title": "Hashrate Growth" + "title": "Hashrate chart" }, "blocktime": { "title": "Blocktime chart" @@ -20,10 +20,7 @@ angular.module('BlocksApp').controller('StatsController', function($stateParams, "title": "Difficulty chart" }, "miner_hashrate": { - "title": "Miner Hashrate Distribution" - }, - "The_bomb_chart": { - "title": "The bomb chart" + "title": "Miner distribution" } } @@ -895,969 +892,6 @@ angular.module('BlocksApp').controller('StatsController', function($stateParams, // arg1 now equals 'three' callback(null, 'done'); } - } - } - } -}) -.directive('etcTheBombChartOrig', function($http) { - return { - restrict: 'E', - template: '', - scope: true, - link: function(scope, elem, attrs) { - $http.post("/stats", {"action": "hashrates"}) - .then(function(res) { - //console.log(res.data); - - scope.init(res.data, '#bombchart'); - }); - - /** - * Created by chenxiangyu on 2016/8/5. - */ - scope.init = function(dataset, chartid) { - async.waterfall([ - myFirstFunction, - mySecondFunction, - myLastFunction - ], function (err, result) { - // result now equals 'done' - //console.log("all done1"); - - return result; - }); - - function myFirstFunction(callback) { - /* - request('http://drawpie.com/etc_hash_rate_api', function (error, response, body) { - if (!error && response.statusCode == 200) { - - var hashrate = JSON.parse(body); - //console.log(hashrate); - callback(null, hashrate, 'two'); - } - }); - */ - - callback(null, dataset, 'two'); - //callback(null, 'one', 'two'); - } - - function mySecondFunction(arg1, arg2, callback) { - // arg1 now equals 'one' and arg2 now equals 'two' - - //console.log(112); - //console.log(arg1); - var day = moment("2016-08-10"); - - var bomb_array =[]; - for(i=2000000;i<4500000;i = i +50000){ - console.log(i); - //Math.pow(2, (block_number/100000)-2); - console.log(Math.pow(2, (i/100000)-2)); - - //bomb_array.push({Date :day.unix(), Value : Math.pow(2, (i/100000000000)-2) + 10677580591563}); - bomb_array.push({Date :day.unix(), Value : Math.pow(2, (i/100000)-2)+8000000000000}); - - day.add(14*50000, 's'); - //console.log(day.format()) - } - - //console.log(bomb_array); - - - //console.log(window.screen.availWidth); - var width1 = parseInt(d3.select(chartid).style("width")); - - var margin = {top: 0, right: 50, bottom: 50, left: 100}, - //var margin = {top: 30, right: 0, bottom: 0, left: 0}, - // For Responsive web design, get window.innerWidth - //width = window.innerWidth - margin.left - margin.right, - width = width1 - margin.left - margin.right, - //width = window.screen.availWidth - margin.left - margin.right, - height = 400 - margin.top - margin.bottom; - - var x = d3.time.scale().range([0, width]); - var y = d3.scale.linear().range([height, 0]); - - // For Responsive web design - //When window.innerWidth < 800 , Reduce the ticks to 2 - - - var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom") - //.tickFormat(d3.time.format("%x %H:%M")) - .tickFormat(d3.time.format("%x")) - .ticks(8); - - - var yAxis = d3.svg.axis() - .scale(y) - .orient("left") - .tickFormat(d3.format("s")) - .tickFormat(function(d){return d3.format("s")(d) +'H/s';}) - .ticks(5); - - - var area = d3.svg.area() - .x(function(d) { return x(d.timestamp*1000); }) - .y0(height) - .y1(function(d) { return y(d.difficulty); }); - - var valueline = d3.svg.line() - .x(function(d) { return x(d.timestamp*1000); }) - .y(function(d) { return y(d.difficulty); }); - - /* - var valueline_bomb = d3.svg.line() - .x(function(d) { return x(d.Date*1000); }) - .y(function(d) { return y(d.Value); }); - */ - - var svg = d3.select(chartid) - //.append("svg") - .attr("width", width + margin.left + margin.right) - - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", - "translate(" + margin.left + "," + margin.top + ")"); - - - - - - // function for the x grid lines - function make_x_axis() { - return d3.svg.axis() - .scale(x) - .orient("bottom") - .ticks(8) - } - - // function for the y grid lines - function make_y_axis() { - return d3.svg.axis() - .scale(y) - .orient("left") - .ticks(8) - } - - - - var data = arg1.hashrates; - - // Scale the range of the data - //x.domain(d3.extent(data, function(d) { return d.timestamp*1000; })); - x.domain([1470009600*1000,1504224000*1000]); - y.domain([d3.min(data, function(d) { return d.difficulty; }), d3.max(data, function(d) { return d.difficulty; })]); - - // Add the filled area - svg.append("path") - .datum(data) - .attr("class", "area") - .attr("d", area); - - // Draw the x Grid lines - svg.append("g") - .attr("class", "grid") - .attr("transform", "translate(0," + height + ")") - .call(make_x_axis() - .tickSize(-height, 0, 0) - .tickFormat("") - ); - - // Draw the y Grid lines - svg.append("g") - .attr("class", "grid") - .call(make_y_axis() - .tickSize(-width, 0, 0) - .tickFormat("") - ); - - // Add the valueline path. - svg.append("path") - .attr("d", valueline(data)); - - svg.selectAll("circle") - .data(bomb_array) - .enter() - .append("circle") - .attr("cx", function (d) { return x(new Date(d.Date*1000)) }) - .attr("cy", function (d) { return y(d.Value); }) - .attr("r", function (d) { return 3; }) - .style("fill", function(d) { - if(d.Value < 8250000000000){ - return "black"; - } - else{ - return "red"; - } - - - }); - - // Add the X Axis - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + height + ")") - .call(xAxis); - - // Add the Y Axis - svg.append("g") - .attr("class", "y axis") - .call(yAxis); - - - - // Add Tooltip - var focus = svg.append("g") - .attr("class", "focus") - .style("display", "none"); - - focus.append("circle") - .attr("r", 4.5); - - focus.append("text") - .attr("x", 9) - .attr("dy", ".35em"); - - - svg.append("rect") - .attr("class", "overlay") - .attr("width", width) - .attr("height", height) - .on("mouseover", function() { focus.style("display", null); }) - .on("mouseout", function() { focus.style("display", "none"); }) - .on("mousemove", mousemove); - - - function mousemove() { - var x0 = x.invert(d3.mouse(this)[0]); - //console.log(moment(x0).unix()); - - - var s1 = _.minBy(data, function(d) { - //console.log(d.unixtime); - return Math.abs(moment(x0).unix()-d.unixtime); - }); - - //console.log(moment(s1.unixtime*1000).format()); - //console.log(s1.instantHashrate); - - - - //focus.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")"); - focus.attr("transform", "translate(" + x(moment(x0).unix()*1000) + "," + y(s1.difficulty) + ")"); - } - - - - - callback(null, 'three'); - } - - function myLastFunction(arg1, callback) { - // arg1 now equals 'three' - callback(null, 'done'); - } - - - } - } - } -}) -.directive('etcTheBombChart', function($http) { - return { - restrict: 'E', - template: '', - scope: true, - link: function(scope, elem, attrs) { - $http.post("/stats", {"action": "hashrates", "range": 12 * 30 * 24 * 60 * 60 }) - .then(function(res) { - //console.log(res.data); - - res.data.hashrates.forEach(function(d) { d.difficulty = d.difficulty / d.blockTime; }); // FIXME - scope.init(res.data, '#bombchartwithecip1010'); - }); - - /** - * Created by chenxiangyu on 2016/8/5. - */ - scope.init = function(dataset, chartid) { - async.waterfall([ - myFirstFunction, - get_ave_block_time, - mySecondFunction, - myLastFunction - ], function (err, result) { - // result now equals 'done' - //console.log("all done1"); - - return result; - }); - - function myFirstFunction(callback) { - - /* - request('http://drawpie.com/etc_hash_rate_api', function (error, response, body) { - if (!error && response.statusCode == 200) { - - var hashrate = JSON.parse(body); - //console.log(hashrate); - callback(null, hashrate); - } - }); - */ - //callback(null, hashrate); - callback(null, dataset); - - - - //callback(null, 'one', 'two'); - } - - function get_ave_block_time(arg1, callback) { - - - /* - request('http://drawpie.com/etc_avg_block_time', function (error, response, body) { - if (!error && response.statusCode == 200) { - - var ave_block_time = JSON.parse(body); - //console.log(hashrate); - callback(null, arg1, ave_block_time); - } - }); - */ - //callback(null, arg1, ave_block_time); - callback(null, arg1, 'three'); - - - - //callback(null, 'one', 'two'); - } - - function mySecondFunction(arg1, arg2, callback) { - // arg1 now equals 'one' and arg2 now equals 'two' - - //console.log(112); - //console.log(arg2.base_diff); - //console.log(arg2.etc_avg_block_time[0].array); - ////var ave_block_time_array = arg2.etc_avg_block_time[0].array; - ////ave_block_time_array.reverse(); - ////var ave_block_time_array_sliced = _.slice(ave_block_time_array,0,15); - //console.log(ave_block_time_array_sliced); - - ////var ave_block_time_array_sliced_lodashed = _.meanBy(ave_block_time_array_sliced, function(d) { return d.avg_block_time; }); - var ave_block_time_array_sliced_lodashed = _.meanBy(arg1.hashrates, function(d) { return d.blockTime; }); // FIXME - //console.log("ave_block_time_array_sliced_lodashed"); - //console.log(ave_block_time_array_sliced_lodashed); - - var start_count_block = 2250000; // 1473790866 - var day = moment.unix(1473790866); - var day_with_ECIP_1010 = moment.unix(1473790866); - - // var day = moment("2016-08-10"); - //var day_with_ECIP_1010 = moment("2016-08-10"); - - var bomb_array =[]; - var bomb_array_with_ECIP_1010 =[]; - - //var base_diff = arg2.base_diff; - var base_diff = 7580000000000.00; // FIXME - - - - for(i=start_count_block;i<4500000;i = i +50000){ - //console.log(i); - //Math.pow(2, (block_number/100000)-2); - //console.log(Math.pow(2, (i/100000)-2)); - - //bomb_array.push({Date :day.unix(), Value : Math.pow(2, (i/100000000000)-2) + 10677580591563}); - - switch (true) { - case (i<3000000): - - - //console.log(i); - //Math.pow(2, (block_number/100000)-2); - //console.log(Math.pow(2, (i/100000)-2)); - - //bomb_array.push({Date :day.unix(), Value : Math.pow(2, (i/100000000000)-2) + 10677580591563}); - bomb_array.push({ - Date :day.unix(), - Value : Math.pow(2, (i/100000)-2)+base_diff, - number : i - }); - - break; - - case (i>=3000000): - - if (i == 3000000){ - //console.log("Block 3000000 time "); - //console.log(day.format()); - } - //console.log(i); - //Math.pow(2, (block_number/100000)-2); - //console.log(Math.pow(2, 28)); - - //bomb_array.push({Date :day.unix(), Value : Math.pow(2, (i/100000000000)-2) + 10677580591563}); - bomb_array.push({ - Date :day.unix(), - Value : Math.pow(2, (i/100000)-2)+base_diff+100000000000, - number : i - }); - - break; - - } - - /* - bomb_array.push({ - Date :day.unix(), - Value : Math.pow(2, (i/100000)-2)+base_diff, - number : i - }); - */ - - day.add(ave_block_time_array_sliced_lodashed*50000, 's'); - //console.log(day.format()) - } - - for(i=start_count_block;i<6500000;i = i +50000){ - - - //console.log(1123); - - switch (true) { - case (i<3000000): - day = "Sunday"; - - //console.log(i); - //Math.pow(2, (block_number/100000)-2); - //console.log(Math.pow(2, (i/100000)-2)); - - //bomb_array.push({Date :day.unix(), Value : Math.pow(2, (i/100000000000)-2) + 10677580591563}); - bomb_array_with_ECIP_1010.push({ - Date :day_with_ECIP_1010.unix(), - Value : Math.pow(2, (i/100000)-2)+base_diff, - number : i - }); - - break; - - case (i>=3000000 && i<5000000 ): - day = "Monday"; - - //console.log(i); - //Math.pow(2, (block_number/100000)-2); - //console.log(Math.pow(2, 28)); - - //bomb_array.push({Date :day.unix(), Value : Math.pow(2, (i/100000000000)-2) + 10677580591563}); - bomb_array_with_ECIP_1010.push({ - Date :day_with_ECIP_1010.unix(), - Value : Math.pow(2, 28)+base_diff-100000000000, - number : i - }); - - break; - - case (i>=5000000): - day = "Monday"; - - //console.log(i); - //Math.pow(2, (block_number/100000)-2); - //console.log(Math.pow(2, (i/100000)-2-20)); - - //bomb_array.push({Date :day.unix(), Value : Math.pow(2, (i/100000000000)-2) + 10677580591563}); - bomb_array_with_ECIP_1010.push({ - Date :day_with_ECIP_1010.unix(), - Value : Math.pow(2, (i/100000)-2-20)+base_diff-100000000000, - number : i - }); - - break; - - } - - - - day_with_ECIP_1010.add(ave_block_time_array_sliced_lodashed*50000, 's'); - //console.log(day.format()) - } - - - //console.log(bomb_array); - - - //console.log(window.screen.availWidth); - var width1 = parseInt(d3.select(chartid).style("width")); - - var margin = {top: 0, right: 50, bottom: 50, left: 100}, - //var margin = {top: 30, right: 0, bottom: 0, left: 0}, - // For Responsive web design, get window.innerWidth - //width = window.innerWidth - margin.left - margin.right, - width = width1 - margin.left - margin.right, - //width = window.screen.availWidth - margin.left - margin.right, - height = 400 - margin.top - margin.bottom; - - // FIXME - if (width < 0) { - width = 1000; - } - - var x = d3.time.scale().range([0, width]); - var y = d3.scale.linear().range([height, 0]); - - // For Responsive web design - //When window.innerWidth < 800 , Reduce the ticks to 2 - - - var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom") - //.tickFormat(d3.time.format("%x %H:%M")) - .tickFormat(d3.time.format("%x")) - .ticks(8); - - - var yAxis = d3.svg.axis() - .scale(y) - .orient("left") - .tickFormat(d3.format("s")) - .tickFormat(function(d){return d3.format("s")(d) +'H/s';}) - .ticks(5); - - - var area = d3.svg.area() - .x(function(d) { return x(d.timestamp*1000); }) - .y0(height) - .y1(function(d) { return y(d.difficulty); }); - - var valueline = d3.svg.line() - .x(function(d) { return x(d.timestamp*1000); }) - .y(function(d) { return y(d.difficulty); }); - - - var valueline_bomb = d3.svg.line() - .x(function(d) { return x(d.Date*1000); }) - .y(function(d) { return y(d.Value); }); - - var valueline_bomb_with_ECIP_1010 = d3.svg.line() - .x(function(d) { return x(d.Date*1000); }) - .y(function(d) { return y(d.Value); }); - - - - - var svg = d3.select(chartid) - //.append("svg") - .attr("width", width + margin.left + margin.right) - - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", - "translate(" + margin.left + "," + margin.top + ")"); - - - - - - // function for the x grid lines - function make_x_axis() { - return d3.svg.axis() - .scale(x) - .orient("bottom") - .ticks(8) - } - - // function for the y grid lines - function make_y_axis() { - return d3.svg.axis() - .scale(y) - .orient("left") - .ticks(8) - } - - - - var data = arg1.hashrates; - - // Scale the range of the data - //x.domain(d3.extent(data, function(d) { return d.timestamp*1000; })); - //x.domain([1470009600*1000,1504224000*1000]); - x.domain([1470009600*1000,1535760000*1000]); - y.domain([d3.min(data, function(d) { return d.difficulty; }), d3.max(data, function(d) { return d.difficulty; })]); - - // Add the filled area - svg.append("path") - .datum(data) - .attr("class", "area") - .attr("d", area); - - // Draw the x Grid lines - svg.append("g") - .attr("class", "grid") - .attr("transform", "translate(0," + height + ")") - .call(make_x_axis() - .tickSize(-height, 0, 0) - .tickFormat("") - ); - - // Draw the y Grid lines - svg.append("g") - .attr("class", "grid") - .call(make_y_axis() - .tickSize(-width, 0, 0) - .tickFormat("") - ); - - // Add the valueline path. - svg.append("path") - .attr("d", valueline(data)); - - svg.append("path") - .attr("d", valueline_bomb(bomb_array)); - - svg.append("path") - .attr("d", valueline_bomb_with_ECIP_1010(bomb_array_with_ECIP_1010)); - - - - - svg.selectAll("circle") - .data(bomb_array) - .enter() - .append("circle") - .attr("cx", function (d) { return x(new Date(d.Date*1000)) }) - .attr("cy", function (d) { - - if(d.number < 3000000){ - return y(d.Value); - } - else{ - return y(d.Value); - } - //return y(d.Value)-10; - - }) - .attr("r", function (d) { return 3; }) - .style("fill", function(d) { - /* - if(d.Value < 8250000000000){ - return "black"; - } - else{ - return "red"; - } - */ - return "red"; - - }); - - svg.selectAll("circle_with_ECIP_1010") - .data(bomb_array_with_ECIP_1010) - .enter() - .append("circle") - .attr("cx", function (d) { return x(new Date(d.Date*1000)) }) - .attr("cy", function (d) { - - if(d.number < 3000000){ - return y(d.Value); - } - else{ - return y(d.Value); - } - //return y(d.Value)-10; - - }) - .attr("r", function (d) { return 3; }) - .style("fill", function(d) { - - if(d.number < 3000000){ - return "red"; - } - else{ - return "green"; - } - - }); - - // Add the X Axis - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + height + ")") - .call(xAxis); - - // Add the Y Axis - svg.append("g") - .attr("class", "y axis") - .call(yAxis); - - //append label - svg.append("rect") - .attr("x", 50) - .attr("y", 10) - .style("fill","lightsteelblue") - .attr("stroke-width", 2) - .attr("stroke", "steelblue") - .attr("width", 10) - .attr("height", 10); - - //console.log(_.last(arg1.etc_hashrate).difficulty); - //console.log(d3.format(".3s")(_.last(arg1.etc_hashrate).difficulty)); - //d3.format("s")(d) +'H/s' - //console.log(_.last(arg1.etc_hashrate).unixtime); - - - svg.append("text") - .attr("x", 70) - .attr("y", 10) - .text("Current difficulty : " + d3.format(".3s")(_.last(arg1.hashrates).difficulty)+" , " +new Date(_.last(arg1.hashrates).unixtime*1000)) - //.attr("text-anchor", "middle") - .attr("dy", "10px") - .attr("font-family", "sans-serif") - .attr("font-size", "20px"); - - svg.append("circle") - .attr("cx", 50+4) - .attr("cy", 10+30) - .style("fill","red") - .attr("r", 5); - - svg.append("text") - .attr("x", 50+20) - .attr("y", 35) - .text("Prediction of future difficulty, without ECIP-1010") - //.attr("text-anchor", "middle") - .attr("dy", "10px") - .attr("font-family", "sans-serif") - .attr("font-size", "20px"); - - svg.append("circle") - .attr("cx", 50+4) - .attr("cy", 10+30+25) - .style("fill","green") - .attr("r", 5); - - svg.append("text") - .attr("x", 50+20) - .attr("y", 35+25) - .text("Prediction of future difficulty, with ECIP-1010") - //.attr("text-anchor", "middle") - .attr("dy", "10px") - .attr("font-family", "sans-serif") - .attr("font-size", "20px"); - - //add mark - - //console.log(bomb_array_with_ECIP_1010); - - - var block_3000000_time = _.find(bomb_array_with_ECIP_1010, function(d) { return d.number == 3000000; }); - - //console.log(block_3000000_time); - //console.log(block_3000000_time.Date); - - svg.append("line") - .attr("x1", x(new Date(_.last(arg1.hashrates).unixtime*1000))+10) - .attr("y1", 0+270) - .attr("x2", x(new Date(_.last(arg1.hashrates).unixtime*1000))+10) - .attr("y2", 10+270) - .attr("stroke-width", 1) - .attr("stroke", "black"); - - svg.append("line") - .attr("x1", x(new Date(block_3000000_time.Date*1000))) - .attr("y1", 0+270) - .attr("x2", x(new Date(block_3000000_time.Date*1000))) - .attr("y2", 10+270) - .attr("stroke-width", 1) - //.style("stroke-dasharray", ("3, 3")) - .attr("stroke", "black"); - - svg.append("line") - .attr("x1", x(new Date(block_3000000_time.Date*1000))) - .attr("y1", 0+270-80) - .attr("x2", x(new Date(block_3000000_time.Date*1000))) - .attr("y2", 10+270) - .attr("stroke-width", 1) - .style("stroke-dasharray", ("3, 3")) - .attr("stroke", "black"); - - svg.append("text") - .attr("x", x(new Date(block_3000000_time.Date*1000))) - //.attr("x", x(new Date(_.last(arg1.etc_hashrate).unixtime*1000))+10) - .attr("y", 0+260-80-10-15) - .text("ECIP-1010 Deploy, Block 3000000") - .attr("text-anchor", "middle") - .attr("dy", "10px") - .attr("font-family", "sans-serif") - .attr("font-size", "20px"); - - svg.append("text") - .attr("x", x(new Date(block_3000000_time.Date*1000))) - //.attr("x", x(new Date(_.last(arg1.etc_hashrate).unixtime*1000))+10) - .attr("y", 0+260-80-10) - .text(new Date(block_3000000_time.Date*1000)+" (expected)") - .attr("text-anchor", "middle") - .attr("dy", "10px") - .attr("font-family", "sans-serif") - .attr("font-size", "20px"); - - - - svg.append("line") - .attr("x1", x(new Date(_.last(arg1.hashrates).unixtime*1000))+10) - .attr("y1", 5+270) - .attr("x2", x(new Date(block_3000000_time.Date*1000))) - .attr("y2", 5+270) - .attr("stroke-width", 1) - .attr("stroke", "black"); - - var duration = block_3000000_time.Date - _.last(arg1.hashrates).unixtime; - //console.log(duration); - //console.log(moment.duration(duration, 'seconds').humanize()); - - - - svg.append("text") - .attr("x", x(new Date(( duration/2 + _.last(arg1.hashrates).unixtime ) *1000))+0) - //.attr("x", x(new Date(_.last(arg1.etc_hashrate).unixtime*1000))+10) - .attr("y", 0+260) - .text(moment.duration(duration, 'seconds').humanize()) - .attr("text-anchor", "middle") - .attr("dy", "10px") - .attr("font-family", "sans-serif") - .attr("font-size", "20px"); - - - var block_4000000_time = _.find(bomb_array_with_ECIP_1010, function(d) { return d.number == 4000000; }); - - var duration_30_40 = block_4000000_time.Date - block_3000000_time.Date; - //console.log(duration_30_40); - //console.log(moment.duration(duration_30_40, 'seconds').humanize()); - - svg.append("line") - .attr("x1", x(new Date(block_3000000_time.Date*1000))) - .attr("y1", 5+270) - .attr("x2", x(new Date(block_4000000_time.Date*1000))) - .attr("y2", 5+270) - .attr("stroke-width", 1) - .attr("stroke", "black"); - - //((block_4000000_time.Date-block_3000000_time.Date)/2+block_3000000_time.Date) - - svg.append("text") - .attr("x", x(new Date(((block_4000000_time.Date-block_3000000_time.Date)/2+block_3000000_time.Date)*1000))) - .attr("y", 0+260) - .text(moment.duration(duration_30_40, 'seconds').humanize()) - .attr("text-anchor", "middle") - .attr("dy", "10px") - .attr("font-family", "sans-serif") - .attr("font-size", "20px"); - - svg.append("line") - .attr("x1", x(new Date(block_4000000_time.Date*1000))) - .attr("y1", 0+270) - .attr("x2", x(new Date(block_4000000_time.Date*1000))) - .attr("y2", 10+270) - .attr("stroke-width", 1) - .attr("stroke", "black"); - - - var block_6000000_time = _.find(bomb_array_with_ECIP_1010, function(d) { return d.number == 6000000; }); - - var duration_40_60 = block_6000000_time.Date - block_4000000_time.Date; - //console.log(duration_40_60); - //console.log(moment.duration(duration_40_60, 'seconds').humanize()); - - svg.append("line") - .attr("x1", x(new Date(block_4000000_time.Date*1000))) - .attr("y1", 5+270) - .attr("x2", x(new Date(block_6000000_time.Date*1000))) - .attr("y2", 5+270) - .attr("stroke-width", 1) - .attr("stroke", "black"); - - svg.append("line") - .attr("x1", x(new Date(block_6000000_time.Date*1000))) - .attr("y1", 0+270) - .attr("x2", x(new Date(block_6000000_time.Date*1000))) - .attr("y2", 10+270) - .attr("stroke-width", 1) - .attr("stroke", "black"); - - // ((block_6000000_time.Date-block_4000000_time.Date)/2+block_4000000_time.Date); - - svg.append("text") - //.attr("x", x(new Date((block_4000000_time.Date*1000)))) - .attr("x", x(new Date(( ((block_6000000_time.Date-block_4000000_time.Date)/2+block_4000000_time.Date)*1000)))) - .attr("y", 0+260) - .text(moment.duration(duration_40_60, 'seconds').humanize()) - .attr("text-anchor", "middle") - .attr("dy", "10px") - .attr("font-family", "sans-serif") - .attr("font-size", "20px"); - - - - - // Add Tooltip - var focus = svg.append("g") - .attr("class", "focus") - .style("display", "none"); - - focus.append("circle") - .attr("r", 4.5); - - focus.append("text") - .attr("x", 9) - .attr("dy", ".35em"); - - - svg.append("rect") - .attr("class", "overlay") - .attr("width", width) - .attr("height", height) - .on("mouseover", function() { focus.style("display", null); }) - .on("mouseout", function() { focus.style("display", "none"); }) - .on("mousemove", mousemove); - - - function mousemove() { - var x0 = x.invert(d3.mouse(this)[0]); - //console.log(moment(x0).unix()); - - - var s1 = _.minBy(data, function(d) { - //console.log(d.unixtime); - return Math.abs(moment(x0).unix()-d.unixtime); - }); - - //console.log(moment(s1.unixtime*1000).format()); - //console.log(s1.instantHashrate); - - - - //focus.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")"); - focus.attr("transform", "translate(" + x(moment(x0).unix()*1000) + "," + y(s1.difficulty) + ")"); - } - - - - - callback(null, 'four'); - } - function myLastFunction(arg1, callback) { - // arg1 now equals 'three' - callback(null, 'done'); - } - - } } } diff --git a/public/tpl/header.html b/public/tpl/header.html index f00845a14..66c228a7f 100755 --- a/public/tpl/header.html +++ b/public/tpl/header.html @@ -107,10 +107,6 @@ Blocktime Chart
  • -
  • - - The bomb chart -
  • diff --git a/public/views/stats/index.html b/public/views/stats/index.html index 26a8ead76..4ad65d840 100644 --- a/public/views/stats/index.html +++ b/public/views/stats/index.html @@ -7,7 +7,6 @@ -
    From f281d9157e77b3c8777086d7795e430d89c2ebcb Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:17 +0900 Subject: [PATCH 13/46] cleanup: drop broken summary-stats & useEthFiat * they aren't being maintained for years and no one use them * updated custom.css to fix search bar on mobile --- README.md | 2 - config.example.json | 2 - lib/etherUnits.js | 11 +-- public/css/custom.css | 26 +++-- public/js/controllers/AddressController.js | 18 +--- public/js/controllers/HomeController.js | 39 -------- public/views/address.html | 8 +- public/views/home.html | 10 +- public/views/site-notes.html | 2 +- public/views/summary-stats.html | 105 --------------------- routes/fiat.js | 33 ------- routes/index.js | 2 - views/index.ejs | 2 +- 13 files changed, 31 insertions(+), 229 deletions(-) delete mode 100644 public/views/summary-stats.html delete mode 100644 routes/fiat.js diff --git a/README.md b/README.md index 2bdbd6405..0a1e219da 100644 --- a/README.md +++ b/README.md @@ -54,9 +54,7 @@ Basic settings: "linkedin": "https://www.linkedin.com/company/ethereum-classic", "github": "https://github.com/ethereumclassic", "logo": "/img/explorer-logo.png", - "customCss": "green-haze.min.css", "copyright": "2018 © Ethereum Classic.", - "useEthFiat": false, "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, diff --git a/config.example.json b/config.example.json index b1387a365..f526bdde7 100644 --- a/config.example.json +++ b/config.example.json @@ -22,9 +22,7 @@ "linkedin": "https://www.linkedin.com/company/ethereum-classic", "github": "https://github.com/ethereumproject", "logo": "/img/explorer-logo.png", - "customCss": "green-haze.min.css", "copyright": "2018 © Ethereum Classic.", - "useEthFiat": false, "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, diff --git a/lib/etherUnits.js b/lib/etherUnits.js index cf598f98d..7b9b327e9 100644 --- a/lib/etherUnits.js +++ b/lib/etherUnits.js @@ -36,15 +36,6 @@ etherUnits.getValueOfUnit = function(unit) { } return new BigNumber(unitValue, 10); } -etherUnits.fiatToWei = function(number, pricePerEther) { - var returnValue = new BigNumber(String(number)).div(pricePerEther).times(this.getValueOfUnit('ether')).round(0); - return returnValue.toString(10); -} - -etherUnits.toFiat = function(number, unit, multi) { - var returnValue = new BigNumber(this.toEther(number, unit)).times(multi).round(5); - return returnValue.toString(10); -} etherUnits.toEther = function(number, unit) { var returnValue = new BigNumber(this.toWei(number, unit)).div(this.getValueOfUnit('ether')); @@ -56,4 +47,4 @@ etherUnits.toWei = function(number, unit) { return returnValue.toString(10); } -module.exports = etherUnits; \ No newline at end of file +module.exports = etherUnits; diff --git a/public/css/custom.css b/public/css/custom.css index 9acefc60f..b941992cb 100755 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -5,13 +5,13 @@ img.logo-default { } .create{background-color:#36c6d3} .truncate-txhash, .truncate-addrhash{ - white-space:nowrap; + white-space:nowrap; overflow:hidden; text-overflow: ellipsis; max-width:220px; } .truncate-addrhash { - max-width:200px; + max-width:200px; } .scrollable { max-height: 400px; @@ -20,7 +20,7 @@ img.logo-default { } #table_txs td, #table_internal_txs td { font-size: 12px; - white-space:nowrap; + white-space:nowrap; overflow:hidden; text-overflow: ellipsis; } @@ -31,7 +31,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 { @@ -53,7 +57,7 @@ img.logo-default { } .home-tx{ font-size: 12px; - white-space:nowrap; + white-space:nowrap; overflow:hidden; text-overflow: ellipsis; } @@ -81,7 +85,7 @@ pre { word-wrap: break-word; } pre.code-js, .verified{ - max-height: 200px; + max-height: 200px; } .code { font-family: Menlo,Monaco,Consolas,"Courier New",monospace; @@ -102,7 +106,7 @@ li.ng-scope { .table-scrollable { margin: 0 !important; } -@media(max-width: 487px) { +@media (max-width: 487px) { .container { margin: 0 !important; } @@ -130,4 +134,10 @@ li.ng-scope { ::-webkit-scrollbar-track { background-color: transparent; } -.page-spinner-bar{margin-top:-84px;margin-left:-98px;top:50%;left:50%;} \ No newline at end of file +@media (max-width: 480px) { + .page-header .page-header-top .top-menu .navbar-nav, + .search-form, .page-header .page-header-top .top-menu .navbar-nav>li.dropdown, + .page-header .search-form .input-group .form-control{width:100%;} + .search-form.open{width:100%!important;} +} +.page-spinner-bar{margin-top:-84px;margin-left:-98px;top:50%;left:50%;} diff --git a/public/js/controllers/AddressController.js b/public/js/controllers/AddressController.js index 025717f72..42c0e687f 100755 --- a/public/js/controllers/AddressController.js +++ b/public/js/controllers/AddressController.js @@ -22,16 +22,6 @@ angular.module('BlocksApp').controller('AddressController', function($stateParam } }); - // fetch ethf balance - if ($scope.settings.useEthFiat) - $http({ - method: 'POST', - url: '/fiat', - data: {"addr": $scope.addrHash} - }).then(function(resp) { - $scope.addr.ethfiat = resp.data.balance; - }); - //fetch transactions var fetchTxs = function() { var table = $("#table_txs").DataTable({ @@ -75,7 +65,7 @@ angular.module('BlocksApp').controller('AddressController', function($stateParam [10, 20, 50, 100, 150, 500], [10, 20, 50, 100, 150, 500] // change per page values here ], - "pageLength": 20, + "pageLength": 20, "order": [ [6, "desc"] ], @@ -85,7 +75,7 @@ angular.module('BlocksApp').controller('AddressController', function($stateParam "infoEmpty": ":(", "infoFiltered": "(filtered from _MAX_ total txs)" }, - "columnDefs": [ + "columnDefs": [ { "targets": [ 5 ], "visible": false, "searchable": false }, {"type": "date", "targets": 6}, {"orderable": false, "targets": [0,2,3,4]}, @@ -115,9 +105,9 @@ angular.module('BlocksApp').controller('AddressController', function($stateParam data: {"addr_trace": $scope.addrHash} }).then(function(resp) { $scope.internal_transactions = resp.data; - }); + }); } - + }) .directive('contractSource', function($http) { return { diff --git a/public/js/controllers/HomeController.js b/public/js/controllers/HomeController.js index 7e79eb58a..847e511b5 100755 --- a/public/js/controllers/HomeController.js +++ b/public/js/controllers/HomeController.js @@ -60,43 +60,4 @@ angular.module('BlocksApp').controller('HomeController', function($rootScope, $s restrict: 'E', templateUrl: '/views/site-notes.html' } -}) -//OLD CODE DONT USE -.directive('summaryStats', function($http) { - return { - restrict: 'E', - templateUrl: '/views/summary-stats.html', - scope: true, - link: function(scope, elem, attrs){ - scope.stats = {}; - - var etcEthURL = "/stats"; - var etcPriceURL = "https://api.coinmarketcap.com/v1/ticker/ethereum-classic/"; - var ethPriceURL = "https://api.coinmarketcap.com/v1/ticker/ethereum/" - scope.stats.ethDiff = 1; - scope.stats.ethHashrate = 1; - scope.stats.usdEth = 1; - $http.post(etcEthURL, {"action": "etceth"}) - .then(function(res){ - scope.stats.etcHashrate = res.data.etcHashrate; - scope.stats.ethHashrate = res.data.ethHashrate; - scope.stats.etcEthHash = res.data.etcEthHash; - scope.stats.ethDiff = res.data.ethDiff; - scope.stats.etcDiff = res.data.etcDiff; - scope.stats.etcEthDiff = res.data.etcEthDiff; - }); - $http.get(etcPriceURL) - .then(function(res){ - scope.stats.usdEtc = parseFloat(res.data[0]["price_usd"]); - scope.stats.usdEtcEth = parseInt(100*scope.stats.usdEtc/scope.stats.usdEth); - }); - $http.get(ethPriceURL) - .then(function(res){ - scope.stats.usdEth = parseFloat(res.data[0]["price_usd"]); - scope.stats.usdEtcEth = parseInt(100*scope.stats.usdEtc/scope.stats.usdEth); - scope.stats.ethChange = parseFloat(res.data.change); - }); - - } - } }); diff --git a/public/views/address.html b/public/views/address.html index 3bd9648d2..0b37b87ab 100644 --- a/public/views/address.html +++ b/public/views/address.html @@ -9,15 +9,11 @@
    - {{ addr.balance | number: 10 }}
    + {{ addr.balance | number: 4 }} {{ settings.symbol }}
    {{ settings.symbol }} Balance
    -
    - {{ addr.ethfiat | number: 10 }} ETH-F balance - -
    -
    +
    {{ addr.mined }} Mined
    diff --git a/public/views/home.html b/public/views/home.html index f69af5d78..14cdb8cab 100755 --- a/public/views/home.html +++ b/public/views/home.html @@ -1,6 +1,5 @@ - + -
    @@ -52,7 +51,7 @@
    -
    +
    @@ -63,8 +62,8 @@
    {{t.timestamp | timeDuration }} ago
    -
    - From {{t.from.substr(0,24)}}... +
    + From {{t.from.substr(0,24)}}... To {{t.to.substr(0,24)}}...
    {{t.value}} {{settings.symbol}}
    @@ -75,4 +74,3 @@
    - diff --git a/public/views/site-notes.html b/public/views/site-notes.html index 808f569a2..9ac25cf74 100644 --- a/public/views/site-notes.html +++ b/public/views/site-notes.html @@ -1,7 +1,7 @@
    -

    This Explorer is under construction

    +

    Welcome to ETC Explorer!

    diff --git a/public/views/summary-stats.html b/public/views/summary-stats.html deleted file mode 100644 index 78c1a1219..000000000 --- a/public/views/summary-stats.html +++ /dev/null @@ -1,105 +0,0 @@ -
    -
    -
    -
    -
    -

    - $ - {{stats.usdEtc}} -

    - ETC Price -
    -
    - -
    -
    -
    -
    - - {{stats.usdEtcEth}}% ETC/ETH USD price - -
    -
    -
    ETC/ETH USD Price
    -
    {{stats.usdEtcEth}}%
    -
    -
    -
    -
    -
    -
    -
    -
    -

    - {{stats.etcHashrate | totalDifficulty}}/s -

    - ETC Avg Hashrate -
    -
    -
    -
    - - {{stats.etcEthHash}}% - -
    -
    -
    ETC/ETH Hashrate
    -
    {{stats.etcEthHash}}%
    -
    -
    -
    -
    -
    -
    -
    -
    -

    - {{stats.etcDiff | totalDifficulty}} -

    - DIFFICULTY -
    -
    - -
    -
    -
    -
    - - {{stats.etcEthDiff}}% etc/eth difficulty - -
    -
    -
    ETC/ETH difficulty
    -
    {{stats.etcEthDiff}}%
    -
    -
    -
    -
    -
    -
    -
    -
    -

    - $ - {{stats.usdEth}} -

    - ETH PRICE -
    -
    - -
    -
    -
    -
    - - {{stats.ethChange}}% change - -
    -
    -
    change
    -
    {{stats.ethChange}}%
    -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/routes/fiat.js b/routes/fiat.js deleted file mode 100644 index 4ebf13a83..000000000 --- a/routes/fiat.js +++ /dev/null @@ -1,33 +0,0 @@ -var http = require('http'); -var etherUnits = require(__lib + "etherUnits.js") - -module.exports = function(req, res) { - var addr = req.body.addr; - if (typeof addr !== "undefined") - addr = addr.toLowerCase(); - else - res.sendStatus(400); - - var options = { - host: 'api.blockcypher.com', - port: '80', - path: '/v1/eth/main/addrs/' + addr + '/balance', - method: 'GET' - }; - - var balance = 0; - http.request(options, function(bcRes) { - bcRes.on('data', function (data) { - try { - balance = JSON.parse(data).balance; - balance = etherUnits.toEther( balance, "wei"); - } catch (e) { - console.error("BC err, probably invalid addr"); - } - res.write(JSON.stringify({"balance": balance})); - res.end(); - }) - }).end(); - -} - diff --git a/routes/index.js b/routes/index.js index 998eb9bbc..1dd61db5e 100644 --- a/routes/index.js +++ b/routes/index.js @@ -12,7 +12,6 @@ module.exports = function(app){ var Token = require('./token'); var compile = require('./compiler'); - var fiat = require('./fiat'); var stats = require('./stats'); var richList = require('./richlist'); @@ -33,7 +32,6 @@ module.exports = function(app){ app.post('/web3relay', web3relay.data); app.post('/compile', compile); - app.post('/fiat', fiat); app.post('/stats', stats); } diff --git a/views/index.ejs b/views/index.ejs index bab84257c..d209f5456 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -31,7 +31,7 @@ - + From 686f081f23cd0ea706eb47823aa7d79d71cbdbda Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:18 +0900 Subject: [PATCH 14/46] cleanup: enforce names for mongodb collection --- db.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db.js b/db.js index 83b922dee..ee7bd2e50 100644 --- a/db.js +++ b/db.js @@ -22,7 +22,7 @@ var Block = new Schema( "timestamp": Number, "blockTime": Number, "uncles": [String] -}); +}, {collection: "Block"}); var Account = new Schema( { @@ -30,7 +30,7 @@ var Account = new Schema( "balance": Number, "blockNumber": Number, "type": {type: Number, default: 0} // address: 0x0, contract: 0x1 -}); +}, {collection: "Account"}); var Contract = new Schema( { @@ -72,7 +72,7 @@ var BlockStat = new Schema( "miner": String, "blockTime": Number, "uncleCount": Number -}); +}, {collection: "BlockStat"}); // create indices Transaction.index({blockNumber:-1}); From 6d2f381bc9a7a2bf2eb8da25be8b9690836d20d4 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:20 +0900 Subject: [PATCH 15/46] cleanup: update copyright year to 2019 --- README.md | 2 +- config.example.json | 2 +- public/tpl/header.html | 10 +--------- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 0a1e219da..5af2c7f3b 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Basic settings: "linkedin": "https://www.linkedin.com/company/ethereum-classic", "github": "https://github.com/ethereumclassic", "logo": "/img/explorer-logo.png", - "copyright": "2018 © Ethereum Classic.", + "copyright": "2019 © Ethereum Classic.", "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, diff --git a/config.example.json b/config.example.json index f526bdde7..597e9f39b 100644 --- a/config.example.json +++ b/config.example.json @@ -22,7 +22,7 @@ "linkedin": "https://www.linkedin.com/company/ethereum-classic", "github": "https://github.com/ethereumproject", "logo": "/img/explorer-logo.png", - "copyright": "2018 © Ethereum Classic.", + "copyright": "2019 © Ethereum Classic.", "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, diff --git a/public/tpl/header.html b/public/tpl/header.html index 66c228a7f..d638b9614 100755 --- a/public/tpl/header.html +++ b/public/tpl/header.html @@ -156,7 +156,7 @@
  • - + Live Network Stats @@ -167,14 +167,6 @@ Statebot.io
  • -
    -
  • - - - Morden network stats - -
  • - From 77f62d0261f924dc4184e53a50be8dc9e2bfa12d Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:22 +0900 Subject: [PATCH 16/46] cleanup: replace geth -> rpc normalize expressions for other supported node clients --- README.md | 4 ++-- config.example.json | 2 +- routes/web3relay.js | 22 +++++++++++----------- tools/blockHelper.js | 6 +++--- tools/patcher.js | 6 +++--- tools/richlist.js | 6 +++--- tools/stats.js | 17 +++++++---------- tools/sync.js | 8 ++++---- 8 files changed, 34 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 5af2c7f3b..b174a6f7d 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Basic settings: ```json { "nodeAddr": "localhost", - "gethPort": 8545, + "rpcPort": 8545, "startBlock": 0, "endBlock": "latest", "quiet": true, @@ -93,7 +93,7 @@ Basic settings: ```nodeAddr``` Your node API RPC address. -```gethPort``` Your node API RPC port. +```rpcPort``` Your node API RPC port. ```startBlock``` This is the start block of the blockchain, should always be 0 if you want to sync the whole ETC blockchain. diff --git a/config.example.json b/config.example.json index 597e9f39b..ceb784a3b 100644 --- a/config.example.json +++ b/config.example.json @@ -1,6 +1,6 @@ { "nodeAddr": "localhost", - "gethPort": 8545, + "rpcPort": 8545, "startBlock": 0, "endBlock": "latest", "quiet": true, diff --git a/routes/web3relay.js b/routes/web3relay.js index c6fa91d30..6d8a46b9b 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -17,7 +17,7 @@ var filterTrace = require('./filters').filterTrace; /*Start config for node connection and sync*/ // load config.json -var config = { nodeAddr: 'localhost', gethPort: 8545 }; +var config = { nodeAddr: 'localhost', rpcPort: 8545 }; try { var local = require('../config.json'); _.extend(config, local); @@ -34,11 +34,11 @@ try { } //Create Web3 connection -console.log('Connecting ' + config.nodeAddr + ':' + config.gethPort + '...'); +console.log('Connecting ' + config.nodeAddr + ':' + config.rpcPort + '...'); if (typeof web3 !== "undefined") { web3 = new Web3(web3.currentProvider); } else { - web3 = new Web3(new Web3.providers.HttpProvider('http://'+config.nodeAddr+':'+config.gethPort)); + web3 = new Web3(new Web3.providers.HttpProvider('http://'+config.nodeAddr+':'+config.rpcPort)); } if (web3.isConnected()) @@ -107,8 +107,8 @@ exports.data = function(req, res){ } else if ("addr_trace" in req.body) { var addr = req.body.addr_trace.toLowerCase(); // need to filter both to and from - // from block to end block, paging "toAddress":[addr], - // start from creation block to speed things up + // from block to end block, paging "toAddress":[addr], + // start from creation block to speed things up // TODO: store creation block var filter = {"fromBlock":"0x1d4c00", "toAddress":[addr]}; web3.trace.filter(filter, function(err, tx) { @@ -119,7 +119,7 @@ exports.data = function(req, res){ res.write(JSON.stringify(filterTrace(tx))); } res.end(); - }) + }) } else if ("addr" in req.body) { var addr = req.body.addr.toLowerCase(); var options = req.body.options; @@ -128,7 +128,7 @@ exports.data = function(req, res){ if (options.indexOf("balance") > -1) { try { - addrData["balance"] = web3.eth.getBalance(addr); + addrData["balance"] = web3.eth.getBalance(addr); addrData["balance"] = etherUnits.toEther(addrData["balance"], 'wei'); } catch(err) { console.error("AddrWeb3 error :" + err); @@ -146,7 +146,7 @@ exports.data = function(req, res){ if (options.indexOf("bytecode") > -1) { try { addrData["bytecode"] = web3.eth.getCode(addr); - if (addrData["bytecode"].length > 2) + if (addrData["bytecode"].length > 2) addrData["isContract"] = true; else addrData["isContract"] = false; @@ -155,7 +155,7 @@ exports.data = function(req, res){ addrData = {"error": true}; } } - + res.write(JSON.stringify(addrData)); res.end(); @@ -178,7 +178,7 @@ exports.data = function(req, res){ res.end(); }); - /* + /* / TODO: Refactor, "block" / "uncle" determinations should likely come later / Can parse out the request once and then determine the path. */ @@ -250,4 +250,4 @@ exports.data = function(req, res){ }; -exports.eth = web3.eth; \ No newline at end of file +exports.eth = web3.eth; diff --git a/tools/blockHelper.js b/tools/blockHelper.js index 9cb243757..5d9e8bdd0 100644 --- a/tools/blockHelper.js +++ b/tools/blockHelper.js @@ -175,7 +175,7 @@ var writeTransactionsToDB = function(config, blockData) { } // load config.json -var config = { nodeAddr: 'localhost', gethPort: 8545, bulkSize: 100 }; +var config = { nodeAddr: 'localhost', rpcPort: 8545, bulkSize: 100 }; try { var local = require('../config.json'); _.extend(config, local); @@ -191,9 +191,9 @@ try { } } -console.log('Connecting ' + config.nodeAddr + ':' + config.gethPort + '...'); +console.log('Connecting ' + config.nodeAddr + ':' + config.rpcPort + '...'); -var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.gethPort.toString())); +var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.rpcPort.toString())); // set the default blocks if it's not provided if (!('blocks' in config) || !(Array.isArray(config.blocks))) { diff --git a/tools/patcher.js b/tools/patcher.js index e7e27545b..ce41a6014 100644 --- a/tools/patcher.js +++ b/tools/patcher.js @@ -147,7 +147,7 @@ var blockIter = function(web3, firstBlock, lastBlock, config) { } // load config.json -var config = { nodeAddr: 'localhost', gethPort: 8545 }; +var config = { nodeAddr: 'localhost', rpcPort: 8545 }; try { var local = require('../config.json'); _.extend(config, local); @@ -163,7 +163,7 @@ try { } } -console.log('Connecting ' + config.nodeAddr + ':' + config.gethPort + '...'); -var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.gethPort.toString())); +console.log('Connecting ' + config.nodeAddr + ':' + config.rpcPort + '...'); +var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.rpcPort.toString())); patchBlocks(config); diff --git a/tools/richlist.js b/tools/richlist.js index 7e3c34258..e20f654b1 100644 --- a/tools/richlist.js +++ b/tools/richlist.js @@ -513,7 +513,7 @@ function readJsonAccounts(json, blockNumber, callback, defaultType = 0) { /** * Start config for node connection and sync */ -var config = { nodeAddr: 'localhost', 'gethPort': 8545 }; +var config = { nodeAddr: 'localhost', 'rpcPort': 8545 }; // load the config.json file try { var loaded = require('../config.json'); @@ -529,9 +529,9 @@ try { //config.quiet = false; //mongoose.set('debug', true); -console.log('Connecting ' + config.nodeAddr + ':' + config.gethPort + '...'); +console.log('Connecting ' + config.nodeAddr + ':' + config.rpcPort + '...'); -var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.gethPort.toString())); +var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.rpcPort.toString())); var useParity = false; if (!process.env.NOPARITY diff --git a/tools/stats.js b/tools/stats.js index 2c912ed25..3a2b0660d 100644 --- a/tools/stats.js +++ b/tools/stats.js @@ -59,7 +59,7 @@ var getStats = function(web3, blockNumber, nextBlock, endNumber, interval, resca } /** - * Checks if the a record exists for the block number + * Checks if the a record exists for the block number * if record exists: abort * if record DNE: write a file for the block */ @@ -81,13 +81,13 @@ var checkBlockDBExistsThenWrite = function(web3, blockData, nextBlock, endNumber new BlockStat(stat).save( function( err, s, count ){ console.log(s) if ( typeof err !== 'undefined' && err ) { - console.log('Error: Aborted due to error on ' + - 'block number ' + blockData.number.toString() + ': ' + + console.log('Error: Aborted due to error on ' + + 'block number ' + blockData.number.toString() + ': ' + err); process.exit(9); } else { console.log('DB successfully written for block number ' + - blockData.number.toString() ); + blockData.number.toString() ); getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan); } }); @@ -107,9 +107,6 @@ var checkBlockDBExistsThenWrite = function(web3, blockData, nextBlock, endNumber }) } -/** On Startup **/ -// geth --rpc --rpcaddr "localhost" --rpcport "8545" --rpcapi "eth,net,web3" - var minutes = 1; statInterval = minutes * 60 * 1000; @@ -143,7 +140,7 @@ if (process.env.RESCAN) { } // load config.json -var config = { nodeAddr: 'localhost', gethPort: 8545, bulkSize: 100 }; +var config = { nodeAddr: 'localhost', rpcPort: 8545, bulkSize: 100 }; try { var local = require('../config.json'); _.extend(config, local); @@ -159,9 +156,9 @@ try { } } -console.log('Connecting ' + config.nodeAddr + ':' + config.gethPort + '...'); +console.log('Connecting ' + config.nodeAddr + ':' + config.rpcPort + '...'); -var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.gethPort.toString())); +var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.rpcPort.toString())); // run updateStats(range, interval, rescan); diff --git a/tools/sync.js b/tools/sync.js index 50805bda3..f2e121416 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -420,11 +420,11 @@ var checkBlockDBExistsThenWrite = function(config, patchData, flush) { **/ /** * nodeAddr: node address - * gethPort: geth port + * rpcPort: rpc port * bulkSize: size of array in block to use bulk operation */ // load config.json -var config = { nodeAddr: 'localhost', gethPort: 8545, bulkSize: 100 }; +var config = { nodeAddr: 'localhost', rpcPort: 8545, bulkSize: 100 }; try { var local = require('../config.json'); _.extend(config, local); @@ -440,10 +440,10 @@ try { } } -console.log('Connecting ' + config.nodeAddr + ':' + config.gethPort + '...'); +console.log('Connecting ' + config.nodeAddr + ':' + config.rpcPort + '...'); // Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost -var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.gethPort.toString())); +var web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.nodeAddr + ':' + config.rpcPort.toString())); // patch missing blocks if (config.patch === true){ From ab5dfea7fb223517181599d5f01d762bd159caeb Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:23 +0900 Subject: [PATCH 17/46] cleanup: rename mongodb as `explorerDB` such a poor naming sense for `blockDB` :joy: --- README.md | 8 ++++---- db.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b174a6f7d..d1b032eca 100644 --- a/README.md +++ b/README.md @@ -128,15 +128,15 @@ $ > use admin $ > db.createUser( { user: "admin", pwd: "", roles: ["root"] } ) ``` -And, You can make Explorer's "blockDB" database with db user accounts "explorer" and password "some_pass_code". +And, You can make Explorer's "explorerDB" database with db user accounts "explorer" and password "some_pass_code". ``` -$ > use blockDB +$ > use explorerDB $ > db.createUser( { user: "explorer", pwd: "", roles: ["dbOwner"] } ) $ > quit() ``` -Above dbuser explorer will full access blockDB and clustor setting will be well used on monitoring the multiple sharding and replication of multiple mongodb instances. +Above dbuser explorer will full access explorerDB and clustor setting will be well used on monitoring the multiple sharding and replication of multiple mongodb instances. Enable database authorization in the MongoDB configuration file /etc/mongodb.conf by appending the following lines: ``` @@ -160,7 +160,7 @@ will show db informations. and You can add modified from ./db.js:103 lines, add auth information and mongodb connect options. ``` -mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/blockDB', { +mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/explorerDB', { useMongoClient: true // poolSize: 5, // rs_name: 'myReplicaSetName', diff --git a/db.js b/db.js index ee7bd2e50..4f27c332a 100644 --- a/db.js +++ b/db.js @@ -96,7 +96,7 @@ module.exports.Transaction = mongoose.model('Transaction'); module.exports.Account = mongoose.model('Account'); mongoose.Promise = global.Promise; -mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/blockDB', { +mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/explorerDB', { useMongoClient: true // poolSize: 5, // rs_name: 'myReplicaSetName', From c54a642a77bcaf34dbcbf2813099f9da18f144f0 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:25 +0900 Subject: [PATCH 18/46] enhancement: improve web3relay load & tx page * make web3relay.js read from db * use Gwei unit for gasPrice * improve tx page * format tx into normalizeTX by @hackmod * web3 tx fetch by @hackmod * fetch tx.status and tx.gasUsed information from getTransactionReceipt * etherscan.io style fix * added block confirmation for tx * added tx fee ( gasused * gasprice ) * added missing db index * fix uncle block search by @naikmyeong --- db.js | 5 ++ lib/etherUnits.js | 5 ++ public/views/block.html | 16 +++--- public/views/tx.html | 49 +++++++++++------ routes/web3relay.js | 117 +++++++++++++++++++++++++++------------- tools/patcher.js | 52 ++++++++++++++++-- tools/sync.js | 52 ++++++++++++++++-- 7 files changed, 229 insertions(+), 67 deletions(-) diff --git a/db.js b/db.js index 4f27c332a..06c3d7c00 100644 --- a/db.js +++ b/db.js @@ -51,10 +51,13 @@ var Transaction = new Schema( "blockHash": String, "blockNumber": Number, "transactionIndex": Number, + "status": Number, "from": {type: String, lowercase: true}, "to": {type: String, lowercase: true}, + "creates": {type: String, lowercase: true}, "value": String, "gas": Number, + "gasUsed": Number, "gasPrice": String, "timestamp": Number, "input": String @@ -78,11 +81,13 @@ var BlockStat = new Schema( Transaction.index({blockNumber:-1}); Transaction.index({from:1, blockNumber:-1}); Transaction.index({to:1, blockNumber:-1}); +Transaction.index({creates:1, blockNumber:-1}); Account.index({balance:-1}); Account.index({balance:-1, blockNumber:-1}); Account.index({type:-1, balance:-1}); Block.index({miner:1}); Block.index({miner:1, blockNumber:-1}); +Block.index({hash:1, number:-1}); mongoose.model('BlockStat', BlockStat); mongoose.model('Block', Block); diff --git a/lib/etherUnits.js b/lib/etherUnits.js index 7b9b327e9..e69d6fe37 100644 --- a/lib/etherUnits.js +++ b/lib/etherUnits.js @@ -42,6 +42,11 @@ etherUnits.toEther = function(number, unit) { return returnValue.toString(10); } +etherUnits.toGwei = function(number, unit) { + var returnValue = new BigNumber(this.toWei(number, unit)).div(this.getValueOfUnit('gwei')); + return returnValue.toString(10); +} + etherUnits.toWei = function(number, unit) { var returnValue = new BigNumber(String(number)).times(this.getValueOfUnit(unit)); return returnValue.toString(10); diff --git a/public/views/block.html b/public/views/block.html index 5f808091b..d8498976e 100644 --- a/public/views/block.html +++ b/public/views/block.html @@ -4,20 +4,20 @@
    - - - + + + - - - + + + - - + + - + - + diff --git a/routes/web3relay.js b/routes/web3relay.js index a34496874..c487fdbd3 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -12,9 +12,10 @@ var BigNumber = require('bignumber.js'); var etherUnits = require(__lib + "etherUnits.js") require( '../db.js' ); -var mongoose = require( 'mongoose' ); -var Block = mongoose.model( 'Block' ); -var Transaction = mongoose.model( 'Transaction' ); +const mongoose = require( 'mongoose' ); +const Block = mongoose.model( 'Block' ); +const Transaction = mongoose.model( 'Transaction' ); +const Market = mongoose.model( 'Market' ); var getLatestBlocks = require('./index').getLatestBlocks; var filterBlocks = require('./filters').filterBlocks; @@ -59,13 +60,13 @@ if (web3.version.node.split('/')[0].toLowerCase().includes('parity')) { var newBlocks = web3.eth.filter("latest"); var newTxs = web3.eth.filter("pending"); -exports.data = function(req, res){ +exports.data = async (req, res) => { console.log(req.body) 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) { @@ -111,7 +112,7 @@ exports.data = function(req, res){ txResponse = doc; } - var latestBlock = web3.eth.blockNumber + 1; + const latestBlock = await web3.eth.blockNumber + 1; txResponse.confirmations = latestBlock - txResponse.blockNumber; @@ -122,6 +123,12 @@ exports.data = function(req, res){ txResponse.gasPriceEther = etherUnits.toEther( new BigNumber(txResponse.gasPrice), "wei"); txResponse.txFee = txResponse.gasPriceEther * txResponse.gasUsed; + if (config.settings.useFiat) { + const latestPrice = await Market.findOne().sort({timestamp: -1}) + txResponse.txFeeUSD = txResponse.txFee * latestPrice.quoteUSD; + txResponse.valueUSD = txResponse.value * latestPrice.quoteUSD; + } + res.write(JSON.stringify(txResponse)); res.end(); }); @@ -190,6 +197,11 @@ exports.data = function(req, res){ } } + if (config.settings.useFiat) { + 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 000000000..2b0ffee77 --- /dev/null +++ b/tools/price.js @@ -0,0 +1,60 @@ +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://min-api.cryptocompare.com/data/price?fsym=${config.settings.symbol}&tsyms=USD`; + + try { + let requestUSD = await fetch(URL); + let quoteUSD = await requestUSD.json(); + console.log(quoteUSD) + + quoteObject = { + timestamp: Math.round( Date.now() / 1000), + quoteUSD: quoteUSD.USD, + } + + 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', rpcPort: 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); From b02da920a9a1abc6c764b6925c9019f701c8c3dc Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:28 +0900 Subject: [PATCH 20/46] enhancement: expose total supply api from database --- routes/index.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/routes/index.js b/routes/index.js index 1dd61db5e..9f43e576c 100644 --- a/routes/index.js +++ b/routes/index.js @@ -2,6 +2,7 @@ var mongoose = require( 'mongoose' ); var Block = mongoose.model( 'Block' ); var Transaction = mongoose.model( 'Transaction' ); +var Account = mongoose.model('Account'); var filters = require('./filters'); var async = require('async'); @@ -27,6 +28,7 @@ module.exports = function(app){ app.post('/tx', getTx); app.post('/block', getBlock); app.post('/data', getData); + app.get('/total', getTotal); app.post('/tokenrelay', Token); app.post('/web3relay', web3relay.data); @@ -35,7 +37,7 @@ module.exports = function(app){ app.post('/stats', stats); } -var getAddr = function(req, res){ +const getAddr = async (req, res) => { // TODO: validate addr and tx var addr = req.body.addr.toLowerCase(); var count = parseInt(req.body.count); @@ -57,15 +59,14 @@ var getAddr = function(req, res){ } } - addrFind.lean(true).sort(sortOrder).skip(start).limit(limit) - .exec("find", function (err, docs) { + addrFind.lean(true).sort(sortOrder).skip(start).limit(limit).exec("find", function (err, docs) { if (docs) data.data = filters.filterTX(docs, addr); else data.data = []; res.write(JSON.stringify(data)); res.end(); - }); + }); }; var getAddrCounter = function(req, res) { @@ -155,6 +156,22 @@ var getData = function(req, res){ } }; +/* + Total supply API code +*/ +var getTotal = function(req, res) { + Account.aggregate([ + { $group: { _id: null, totalSupply: { $sum: '$balance' } } } + ]).exec(function(err, docs) { + if (err) { + res.write("Error getting total supply"); + res.end() + } + res.write(docs[0].totalSupply.toString()); + res.end(); + }); +} + /* temporary blockstats here */ From 899b5ff6c4d489b9500625e8a1b56d5add407a98 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:30 +0900 Subject: [PATCH 21/46] enhancement: web3 1.0 integration * replace rpc port to websocket ( better performance & stability ) * use async, rebased listenBlocks for latest ws connection * modifications to match latest web3 api ( web3.eth.getBlockNumber, web3.eth.net.isListening ) * use web3.eth.subscribe to fetch latest blocks * added custom web3-explorer package to connect with parity-only api * roll backed web3.batch due to lack of technical support --- .travis.yml | 4 +- README.md | 2 +- config.example.json | 2 +- lib/trace.js | 101 --------------- package.json | 5 +- public/css/custom.css | 4 + public/js/main.js | 18 +++ public/tpl/header.html | 48 +------- public/views/address.html | 2 +- public/views/token.html | 6 +- routes/compiler.js | 14 +-- routes/token.js | 29 ++--- routes/web3relay.js | 32 ++--- tools/blockHelper.js | 8 +- tools/patcher.js | 16 +-- tools/price.js | 2 +- tools/richlist.js | 252 ++++++++++++-------------------------- tools/stats.js | 12 +- tools/sync.js | 212 +++++++++++--------------------- 19 files changed, 244 insertions(+), 525 deletions(-) delete mode 100644 lib/trace.js diff --git a/.travis.yml b/.travis.yml index d688b091c..153f46347 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,13 @@ language: node_js sudo: required dist: trusty -node_js: '7' +node_js: '8' env: CXX=g++-4.8 services: - docker before_install: - docker pull trufflesuite/ganache-cli - - docker run -d -p 8545:8545 -p 27017:27017 trufflesuite/ganache-cli + - docker run -d -p 8546:8546 -p 27017:27017 trufflesuite/ganache-cli - varA=`docker ps --no-trunc -q | cut -c 1-12` - docker pull mongo - docker run -d --network="container:$varA" mongo diff --git a/README.md b/README.md index d223affda..cc00bd718 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Basic settings: ```json { "nodeAddr": "localhost", - "rpcPort": 8545, + "wsPort": 8546, "startBlock": 0, "endBlock": "latest", "quiet": true, diff --git a/config.example.json b/config.example.json index 1581d20aa..665786c5e 100644 --- a/config.example.json +++ b/config.example.json @@ -1,6 +1,6 @@ { "nodeAddr": "localhost", - "rpcPort": 8545, + "wsPort": 8546, "startBlock": 0, "endBlock": "latest", "quiet": true, diff --git a/lib/trace.js b/lib/trace.js deleted file mode 100644 index 3feb4590c..000000000 --- a/lib/trace.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @author Alexis Roussel - * @author Peter Pratscher - * @date 2017 - * @license LGPL - * @changelog 2018/05/19 - modified for web3.js 0.20.x using _extend() method. (by hackyminer ) - */ -module.exports = function(web3) { - /** - * @file trace.js - * @author Alexis Roussel - * @date 2017 - * @license LGPL - */ - web3._extend({ - property: 'trace', - methods: [ - new web3._extend.Method({ - name: 'call', - call: 'trace_call', - params: 3, - inputFormatter: [web3._extend.formatters.inputCallFormatter, null, web3._extend.formatters.inputDefaultBlockNumberFormatter] - }), - - new web3._extend.Method({ - name: 'rawTransaction', - call: 'trace_rawTransaction', - params: 2 - }), - - new web3._extend.Method({ - name: 'replayTransaction', - call: 'trace_replayTransaction', - params: 2 - }), - - new web3._extend.Method({ - name: 'block', - call: 'trace_block', - params: 1, - inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter] - }), - - new web3._extend.Method({ - name: 'filter', - call: 'trace_filter', - params: 1 - }), - - new web3._extend.Method({ - name: 'get', - call: 'trace_get', - params: 2 - }), - - new web3._extend.Method({ - name: 'transaction', - call: 'trace_transaction', - params: 1 - }) - ] - }); - - /** - * @file parity.js - * @author Peter Pratscher - * @date 2017 - * @license LGPL - */ - web3._extend({ - property: 'parity', - methods: [ - new web3._extend.Method({ - name: 'pendingTransactions', - call: 'parity_pendingTransactions', - params: 0, - outputFormatter: web3._extend.formatters.outputTransactionFormatter - }), - - new web3._extend.Method({ - name: 'pendingTransactionsStats', - call: 'parity_pendingTransactionsStats', - params: 0 - }), - - new web3._extend.Method({ - name: 'listAccounts', - call: 'parity_listAccounts', - params: 3, - inputFormatter: [null, null, web3._extend.formatters.inputDefaultBlockNumberFormatter] - }), - - new web3._extend.Method({ - name: 'phraseToAddress', - call: 'parity_phraseToAddress', - params: 1 - }) - ] - }); - return web3; -}; diff --git a/package.json b/package.json index c8983cc03..0aa6f9a37 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,13 @@ "serve-favicon": "~2.4.5", "socket.io": "^2.0.4", "solc": "^0.4.19", - "web3": "~0.19.0" + "web3": "1.0.0-beta.36", + "web3-explorer": "1.0.2" }, "devDependencies": { "chai": "^4.1.2", "copyfiles": "^1.2.0", - "ethereumjs-testrpc": "^6.0.3", + "ganache-cli": "^6.4.1", "mocha": "^4.1.0", "request": "^2.83.0" } diff --git a/public/css/custom.css b/public/css/custom.css index e58099beb..0f145a73e 100755 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -31,6 +31,10 @@ img.logo-default { color: #7f90a4; } .eth-stat-title { + font-size: 25px; + text-align: center; +} +.eth-stat-title2 { font-size: 20px; text-align: center; } diff --git a/public/js/main.js b/public/js/main.js index 202dfe542..670f9f458 100755 --- a/public/js/main.js +++ b/public/js/main.js @@ -213,6 +213,24 @@ BlocksApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvide }] } }) + .state('viewcontract', { + url: "/contract", + templateUrl: "views/contract.html", + data: {pageTitle: 'Verify Contract'}, + controller: "ContractController", + resolve: { + deps: ['$ocLazyLoad', function($ocLazyLoad) { + return $ocLazyLoad.load({ + name: 'BlocksApp', + insertBefore: '#ng_load_plugins_before', + files: [ + '/js/controllers/ContractController.js', + '/js/custom.js' + ] + }); + }] + } + }) .state('contract', { url: "/contract/{addr}", templateUrl: "views/contract.html", diff --git a/public/tpl/header.html b/public/tpl/header.html index d638b9614..86abe2682 100755 --- a/public/tpl/header.html +++ b/public/tpl/header.html @@ -47,39 +47,8 @@
  • Accounts
  • -
  • + Tokens
  • - - - - + + - + + + diff --git a/routes/compiler.js b/routes/compiler.js index 9a0f54a0c..5eaedf830 100644 --- a/routes/compiler.js +++ b/routes/compiler.js @@ -37,7 +37,6 @@ var compileSolc = async (req, res) => { var data = { "address": address, - "creationTransaction": "", // deal with this later "compilerVersion": version, "optimization": optimization, "contractName": name, diff --git a/routes/contracts.js b/routes/contracts.js index a239386c1..d03ccca5a 100644 --- a/routes/contracts.js +++ b/routes/contracts.js @@ -1,5 +1,5 @@ /* - Stuff to deal with verified contracts in DB + Stuff to deal with verified contracts in DB */ require( '../db.js' ); @@ -8,9 +8,9 @@ var Contract = mongoose.model( 'Contract' ); exports.addContract = function(contract) { Contract.update( - {address: contract.address}, - {$setOnInsert: contract}, - {upsert: true}, + {address: contract.address}, + {$setOnInsert: contract}, + {upsert: true}, function (err, data) { console.log(data); } @@ -24,7 +24,7 @@ exports.findContract = function(address, res) { console.error("ContractFind error: " + err); console.error("bad address: " + address); res.write(JSON.stringify({"error": true, "valid": false})); - } else if (!doc) { + } else if (!doc || !doc.sourceCode) { res.write(JSON.stringify({"valid": false})); } else { var data = doc; @@ -33,4 +33,4 @@ exports.findContract = function(address, res) { } res.end(); }) -} \ No newline at end of file +} diff --git a/routes/filters.js b/routes/filters.js index d59f06f69..a20e65c26 100644 --- a/routes/filters.js +++ b/routes/filters.js @@ -4,11 +4,11 @@ var BigNumber = require('bignumber.js'); var RLP = require('rlp'); /* - Filter an array of TX + Filter an array of TX */ function filterTX(txs, value) { return txs.map(function(tx){ - return [tx.hash, tx.blockNumber, tx.from, tx.to, etherUnits.toEther(new BigNumber(tx.value), 'ether'), tx.gas, tx.timestamp] + return [tx.hash, tx.blockNumber, tx.from, tx.to, etherUnits.toEther(new BigNumber(tx.value), 'ether'), tx.gas, tx.timestamp, tx.creates] }) } @@ -25,14 +25,14 @@ function filterTrace(txs, value) { } else { if (t.action.to) t.to = t.action.to; - t.from = t.action.from; + t.from = t.action.from; if (t.action.gas) t.gas = new BigNumber(t.action.gas).toNumber(); if ((t.result) && (t.result.gasUsed)) t.gasUsed = new BigNumber(t.result.gasUsed).toNumber(); if ((t.result) && (t.result.address)) t.to = t.result.address; - t.value = etherUnits.toEther( new BigNumber(t.action.value), "wei"); + t.value = etherUnits.toEther( new BigNumber(t.action.value), "wei"); } return t; }) @@ -40,11 +40,11 @@ function filterTrace(txs, value) { function filterBlock(block, field, value) { var tx = block.transactions.filter(function(obj) { - return obj[field]==value; + return obj[field]==value; }); tx = tx[0]; if (typeof tx !== "undefined") - tx.timestamp = block.timestamp; + tx.timestamp = block.timestamp; return tx; } @@ -70,14 +70,14 @@ function filterBlocks(blocks) { /* stupid datatable format */ function datatableTX(txs) { return txs.map(function(tx){ - return [tx.hash, tx.blockNumber, tx.from, tx.to, + return [tx.hash, tx.blockNumber, tx.from, tx.to, etherUnits.toEther(new BigNumber(tx.value), 'wei'), tx.gas, tx.timestamp] }) } function internalTX(txs) { return txs.map(function(tx){ - return [tx.transactionHash, tx.blockNumber, tx.action.from, tx.action.to, + return [tx.transactionHash, tx.blockNumber, tx.action.from, tx.action.to, etherUnits.toEther(new BigNumber(tx.action.value), 'wei'), tx.action.gas, tx.timestamp] }) } diff --git a/routes/token.js b/routes/token.js index 5fde35d47..6173b066b 100644 --- a/routes/token.js +++ b/routes/token.js @@ -25,11 +25,10 @@ module.exports = async (req, res) => { var actualBalance = await eth.getBalance(contractAddress); actualBalance = etherUnits.toEther(actualBalance, 'wei'); var totalSupply = await Token.methods.totalSupply().call(); - // totalSupply = etherUnits.toEther(totalSupply, 'wei')*100; - var decimals = await Token.methods.decimals().call(); var name = await Token.methods.name().call(); var symbol = await Token.methods.symbol().call(); var count = await eth.getTransactionCount(contractAddress); + var tokenData = { "balance": actualBalance, "total_supply": totalSupply, @@ -47,7 +46,6 @@ module.exports = async (req, res) => { var addr = req.body.user.toLowerCase(); try { var tokens = await Token.methods.balanceOf(addr).call(); - // tokens = etherUnits.toEther(tokens, 'wei')*100; res.write(JSON.stringify({"tokens": tokens})); res.end(); } catch (e) { diff --git a/routes/web3relay.js b/routes/web3relay.js index 6ad64646e..46449166d 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -99,9 +99,15 @@ exports.data = async (req, res) => { console.error(err); return; } - if(receipt.status != null) - ttx.status = receipt.status; ttx.gasUsed = receipt.gasUsed; + if(receipt.status) { + ttx.status = receipt.status; + } + if (!tx.to && !tx.creates) { + if (receipt && receipt.contractAddress) { + ttx.creates = receipt.contractAddress; + } + } }); //get timestamp from block var block = web3.eth.getBlock(tx.blockNumber, function(err, block) { diff --git a/tools/patcher.js b/tools/patcher.js index 07dc69c0e..b820aa61e 100644 --- a/tools/patcher.js +++ b/tools/patcher.js @@ -7,8 +7,22 @@ var Web3 = require('web3'); var mongoose = require( 'mongoose' ); var Block = mongoose.model( 'Block' ); var Transaction = mongoose.model( 'Transaction' ); +var Contract = mongoose.model( 'Contract' ); +var TokenTransfer = mongoose.model( 'TokenTransfer' ); -const normalizeTX = async (txData, blockData) => { +const ERC20ABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]; +const ERC20_METHOD_DIC = {"0xa9059cbb":"transfer", "0xa978501e":"transferFrom"}; +const METHOD_DIC = { + "0x930a61a57a70a73c2a503615b87e2e54fe5b9cdeacda518270b852296ab1a377":"Transfer(address,address,uint)", + "0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b":"transfer(address,uint256)", + "0xa978501e4506ecbd340f6e45a48ac5bd126b1c14f03f2210837c8e0b602d4d7b":"transferFrom(address,address,uint)", + "0x086c40f692cc9c13988b9e49a7610f67375e8373bfe7653911770b351c2b1c54":"approve(address,uint)", + "0xf2fde38b092330466c661fc723d5289b90272a3e580e3187d1d7ef788506c557":"transferOwnership(address)", + "0x3bc50cfd0fe2c05fb67c0fe4be91fb10eb723ba30ea8f559d533fcd5fe29be7f":"Released(address,uint)", + "0xb21fb52d5749b80f3182f8c6992236b5e5576681880914484d7f4c9b062e619e":"Released(address indexed, uint indexed)" +}; + +const normalizeTX = async (txData, receipt, blockData) => { var tx = { blockHash: txData.blockHash, blockNumber: txData.blockNumber, @@ -20,20 +34,12 @@ const normalizeTX = async (txData, blockData) => { s: txData.s, v: txData.v, gas: txData.gas, + gasUsed: receipt.gasUsed, gasPrice: String(txData.gasPrice), input: txData.input, transactionIndex: txData.transactionIndex, timestamp: blockData.timestamp }; - // getTransactionReceipt to get contract address and more data - - let receipt; - try { - receipt = await web3.eth.getTransactionReceipt(txData.hash) - } catch(err) { - console.log('Error', err); - } - tx.gasUsed = receipt.gasUsed; if (receipt.status) tx.status = receipt.status; @@ -47,7 +53,7 @@ const normalizeTX = async (txData, blockData) => { return tx; } else { if (receipt && receipt.contractAddress) { - tx.creates = receipt.contractAddress; + tx.creates = receipt.contractAddress.toLowerCase(); } return tx; } @@ -122,13 +128,94 @@ var checkBlockDBExistsThenWrite = function(config, blockData) { /** Break transactions out of blocks and write to DB **/ -var writeTransactionsToDB = function(config, blockData) { +const writeTransactionsToDB = async(config, blockData) => { var bulkOps = []; if (blockData.transactions.length > 0) { for (d in blockData.transactions) { var txData = blockData.transactions[d]; - - var tx = normalizeTX(txData, blockData); + var receipt = await web3.eth.getTransactionReceipt(txData.hash); + var tx = await normalizeTX(txData, receipt, blockData); + // Contact creation tx, Event logs of internal transaction + if (txData.input && txData.input.length > 2) { + // Contact creation tx + if (txData.to == null) { + contractAddress = txData.creates.toLowerCase(); + var contractdb = {} + var isTokenContract = true; + var Token = new web3.eth.Contract(ERC20ABI, contractAddress); + contractdb.owner = txData.from; + contractdb.blockNumber = blockData.number; + contractdb.creationTransaction = txData.hash; + try { + var call = await web3.eth.call({ to: contractAddress, data:web3.utils.sha3("totalSupply()")}); + if (call == '0x') { + isTokenContract = false; + } else { + try { + contractdb.tokenName = await Token.methods.name().call(); + contractdb.decimals = await Token.methods.decimals().call(); + contractdb.symbol = await Token.methods.symbol().call(); + contractdb.totalSupply = await Token.methods.totalSupply().call(); + } catch (err) { + isTokenContract = false; + } + } + } catch (err) { + isTokenContract = false; + } + contractdb.byteCode = await web3.eth.getCode(contractAddress); + if (isTokenContract) { + contractdb.ERC = 2; + } else { + // Normal Contract + contractdb.ERC = 0; + } + // Write to db + Contract.update ( + {address: contractAddress}, + {$setOnInsert: contractdb}, + {upsert: true}, + function (err, data) { + if (err) { + console.log(err); + } + } + ); + } else { + // Internal transaction . write to doc of InternalTx + var transfer = {"blockNumber": "", "number": 0, "from": "", "to": "", "contract":"", "value": 0, "timestamp":0}; + var methodCode = txData.input.substr(0,10); + if (ERC20_METHOD_DIC[methodCode]=="transfer" || ERC20_METHOD_DIC[methodCode]=="transferFrom") { + if (ERC20_METHOD_DIC[methodCode]=="transfer") { + // Token transfer transaction + transfer.from = txData.from; + transfer.to = "0x" + txData.input.substring(34,74); + transfer.value = Number("0x" + txData.input.substring(74)); + } else { + // transferFrom + transfer.from = "0x" + txData.input.substring(34,74); + transfer.to = "0x" + txData.input.substring(74,114); + transfer.value = Number("0x" + txData.input.substring(114)); + } + transfer.method = ERC20_METHOD_DIC[methodCode]; + transfer.hash = txData.hash; + transfer.blockNumber = blockData.number; + transfer.contract = txData.to; + transfer.timestamp = blockData.timestamp; + // Write transfer transaction into db + TokenTransfer.update ( + {hash: transfer.hash}, + {$setOnInsert: transfer}, + {upsert: true}, + function (err, data) { + if (err) { + console.log(err); + } + } + ); + } + } + } bulkOps.push(tx); } Transaction.collection.insert(bulkOps, function( err, tx ){ diff --git a/tools/sync.js b/tools/sync.js index ebdd911ad..4c205d4a0 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -16,8 +16,22 @@ var mongoose = require( 'mongoose' ); var Block = mongoose.model( 'Block' ); var Transaction = mongoose.model( 'Transaction' ); var Account = mongoose.model( 'Account' ); +var Contract = mongoose.model( 'Contract' ); +var TokenTransfer = mongoose.model( 'TokenTransfer' ); + +const ERC20ABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]; +const ERC20_METHOD_DIC = {"0xa9059cbb":"transfer", "0xa978501e":"transferFrom"}; +const METHOD_DIC = { + "0x930a61a57a70a73c2a503615b87e2e54fe5b9cdeacda518270b852296ab1a377":"Transfer(address,address,uint)", + "0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b":"transfer(address,uint256)", + "0xa978501e4506ecbd340f6e45a48ac5bd126b1c14f03f2210837c8e0b602d4d7b":"transferFrom(address,address,uint)", + "0x086c40f692cc9c13988b9e49a7610f67375e8373bfe7653911770b351c2b1c54":"approve(address,uint)", + "0xf2fde38b092330466c661fc723d5289b90272a3e580e3187d1d7ef788506c557":"transferOwnership(address)", + "0x3bc50cfd0fe2c05fb67c0fe4be91fb10eb723ba30ea8f559d533fcd5fe29be7f":"Released(address,uint)", + "0xb21fb52d5749b80f3182f8c6992236b5e5576681880914484d7f4c9b062e619e":"Released(address indexed, uint indexed)" +}; -const normalizeTX = async (txData, blockData) => { +const normalizeTX = async (txData, receipt, blockData) => { var tx = { blockHash: txData.blockHash, blockNumber: txData.blockNumber, @@ -29,20 +43,12 @@ const normalizeTX = async (txData, blockData) => { s: txData.s, v: txData.v, gas: txData.gas, + gasUsed: receipt.gasUsed, gasPrice: String(txData.gasPrice), input: txData.input, transactionIndex: txData.transactionIndex, timestamp: blockData.timestamp }; - // getTransactionReceipt to get contract address and more data - - let receipt; - try { - receipt = await web3.eth.getTransactionReceipt(txData.hash) - } catch(err) { - console.log('Error', err); - } - tx.gasUsed = receipt.gasUsed; if (receipt.status) tx.status = receipt.status; @@ -56,7 +62,7 @@ const normalizeTX = async (txData, blockData) => { return tx; } else { if (receipt && receipt.contractAddress) { - tx.creates = receipt.contractAddress; + tx.creates = receipt.contractAddress.toLowerCase(); } return tx; } @@ -145,7 +151,9 @@ var writeBlockToDB = function(config, blockData, flush) { } if (blockData && blockData.number >= 0) { self.bulkOps.push(new Block(blockData)); - console.log('\t- block #' + blockData.number.toString() + ' inserted.'); + if(!('quiet' in config && config.quiet === true)) { + console.log('\t- block #' + blockData.number.toString() + ' inserted.'); + } } if(flush && self.bulkOps.length > 0 || self.bulkOps.length >= config.bulkSize) { @@ -164,7 +172,9 @@ var writeBlockToDB = function(config, blockData, flush) { process.exit(9); } }else{ - console.log('* ' + blocks.insertedCount + ' blocks successfully written.'); + if(!('quiet' in config && config.quiet === true)) { + console.log('* ' + blocks.insertedCount + ' blocks successfully written.'); + } } }); } @@ -188,11 +198,94 @@ const writeTransactionsToDB = async(config, blockData, flush) => { if (blockData && blockData.transactions.length > 0) { for (d in blockData.transactions) { var txData = blockData.transactions[d]; - - var tx = await normalizeTX(txData, blockData); + var receipt = await web3.eth.getTransactionReceipt(txData.hash); + var tx = await normalizeTX(txData, receipt, blockData); + // Contact creation tx, Event logs of internal transaction + if (txData.input && txData.input.length > 2) { + // Contact creation tx + if (txData.to == null) { + contractAddress = txData.creates.toLowerCase(); + var contractdb = {} + var isTokenContract = true; + var Token = new web3.eth.Contract(ERC20ABI, contractAddress); + contractdb.owner = txData.from; + contractdb.blockNumber = blockData.number; + contractdb.creationTransaction = txData.hash; + try { + var call = await web3.eth.call({ to: contractAddress, data:web3.utils.sha3("totalSupply()")}); + if (call == '0x') { + isTokenContract = false; + } else { + try { + contractdb.tokenName = await Token.methods.name().call(); + contractdb.decimals = await Token.methods.decimals().call(); + contractdb.symbol = await Token.methods.symbol().call(); + contractdb.totalSupply = await Token.methods.totalSupply().call(); + } catch (err) { + isTokenContract = false; + } + } + } catch (err) { + isTokenContract = false; + } + contractdb.byteCode = await web3.eth.getCode(contractAddress); + if (isTokenContract) { + contractdb.ERC = 2; + } else { + // Normal Contract + contractdb.ERC = 0; + } + // Write to db + Contract.update ( + {address: contractAddress}, + {$setOnInsert: contractdb}, + {upsert: true}, + function (err, data) { + if (err) { + console.log(err); + } + } + ); + } else { + // Internal transaction . write to doc of InternalTx + var transfer = {"hash": "", "blockNumber": 0, "from": "", "to": "", "contract":"", "value": 0, "timestamp":0}; + var methodCode = txData.input.substr(0,10); + if (ERC20_METHOD_DIC[methodCode]=="transfer" || ERC20_METHOD_DIC[methodCode]=="transferFrom") { + if (ERC20_METHOD_DIC[methodCode]=="transfer") { + // Token transfer transaction + transfer.from = txData.from; + transfer.to = "0x" + txData.input.substring(34,74); + transfer.value = Number("0x" + txData.input.substring(74)); + } else { + // transferFrom + transfer.from = "0x" + txData.input.substring(34,74); + transfer.to = "0x" + txData.input.substring(74,114); + transfer.value = Number("0x" + txData.input.substring(114)); + } + transfer.method = ERC20_METHOD_DIC[methodCode]; + transfer.hash = txData.hash; + transfer.blockNumber = blockData.number; + transfer.contract = txData.to; + transfer.timestamp = blockData.timestamp; + // Write transfer transaction into db + TokenTransfer.update ( + {hash: transfer.hash}, + {$setOnInsert: transfer}, + {upsert: true}, + function (err, data) { + if (err) { + console.log(err); + } + } + ); + } + } + } self.bulkOps.push(tx); } - console.log('\t- block #' + blockData.number.toString() + ': ' + blockData.transactions.length.toString() + ' transactions recorded.'); + if(!('quiet' in config && config.quiet === true)) { + console.log('\t- block #' + blockData.number.toString() + ': ' + blockData.transactions.length.toString() + ' transactions recorded.'); + } } self.blocks++; @@ -267,12 +360,14 @@ const writeTransactionsToDB = async(config, blockData, flush) => { if(!('quiet' in config && config.quiet === true)) { console.log('Skip: Duplicate transaction key ' + err); } - }else{ + } else { console.log('Error: Aborted due to error on Transaction: ' + err); process.exit(9); } - }else{ - console.log('* ' + tx.insertedCount + ' transactions successfully recorded.'); + } else { + if (!('quiet' in config && config.quiet === true)) { + console.log('* ' + tx.insertedCount + ' transactions successfully recorded.'); + } } }); } @@ -297,12 +392,18 @@ const prepareSync = async (config, callback) => { console.log('Warning: null block data received from the block with hash/number: ' + latestBlock); } else { console.log('Starting block number = ' + blockData.number); + if ('quiet' in config && config.quiet === true) { + console.log("Quiet mode enabled"); + } blockNumber = blockData.number - 1; callback(null, blockNumber); } }); } else { console.log('Starting block number = ' + latestBlock); + if ('quiet' in config && config.quiet === true) { + console.log("Quiet mode enabled"); + } blockNumber = latestBlock - 1; callback(null, blockNumber); } @@ -313,6 +414,9 @@ const prepareSync = async (config, callback) => { }else{ blockNumber = docs[0].number - 1; console.log('Old block found. Starting block number = ' + blockNumber); + if ('quiet' in config && config.quiet === true) { + console.log("Quiet mode enabled"); + } callback(null, blockNumber); } }); @@ -386,7 +490,7 @@ var checkBlockDBExistsThenWrite = function(config, patchData, flush) { if (!b.length){ writeBlockToDB(config, patchData, flush); writeTransactionsToDB(config, patchData, flush); - }else if(!('quiet' in config && config.quiet === true)) { + } else if (!('quiet' in config && config.quiet === true)) { console.log('Block number: ' +patchData.number.toString() + ' already exists in DB.'); } }); From a92888f63d11c8f61147f3e622de89d2a78cadf6 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 04:45:55 +0900 Subject: [PATCH 23/46] cleanup: cleanup tools * merge tools/price.js into tools/sync.js * price ticker enabled by default * remove unused patcher.js and blockHelper.js from tools folder --- README.md | 5 - config.example.json | 1 - package.json | 1 - public/views/address.html | 2 +- public/views/tx.html | 4 +- tools/blockHelper.js | 207 -------------------------- tools/patcher.js | 302 -------------------------------------- tools/price.js | 60 -------- tools/sync.js | 47 ++++++ 9 files changed, 50 insertions(+), 579 deletions(-) delete mode 100644 tools/blockHelper.js delete mode 100644 tools/patcher.js delete mode 100644 tools/price.js diff --git a/README.md b/README.md index 5f44c23a0..364702959 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,6 @@ Basic settings: "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, - "useFiat": false, "miners": { "0xdf7d7e053933b5cc24372f878c90e62dadad5d42": "EtherMine", "0xc91716199ccde49dc4fafaeb68925127ac80443f": "F2Pool", @@ -186,10 +185,6 @@ Enabling richlist requires running a separate process: `npm run rich` -Enabling price conversion requires running a separate process: - -`npm run price` - You can configure intervals (how often a new data point is pulled) and range (how many blocks to go back) with the following: `RESCAN=100:7700000 node tools/stats.js` (New data point every 100 blocks. Go back 7,700,000 blocks). diff --git a/config.example.json b/config.example.json index 7e998a88f..b1e4dc2e6 100644 --- a/config.example.json +++ b/config.example.json @@ -26,7 +26,6 @@ "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, - "useFiat": false, "tokenList": "tokens.json", "miners": { "0xdf7d7e053933b5cc24372f878c90e62dadad5d42": "EtherMine", diff --git a/package.json b/package.json index 05e7f3646..6b7a5cd76 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "sync": "node tools/sync.js", "stats": "node tools/stats.js", "rich": "node tools/richlist.js", - "price": "node tools/price.js", "pretest": "copyfiles app.js app/ ", "test": "mocha --exit" }, diff --git a/public/views/address.html b/public/views/address.html index aa04d7c53..af6adbcd9 100644 --- a/public/views/address.html +++ b/public/views/address.html @@ -13,7 +13,7 @@ {{ settings.symbol }} Balance
    -
    +
    {{ addr.balanceUSD | currency : "$" : 4 }} USD balance
    diff --git a/public/views/tx.html b/public/views/tx.html index 37db630aa..1f6a88477 100644 --- a/public/views/tx.html +++ b/public/views/tx.html @@ -33,11 +33,11 @@
    - + - + diff --git a/tools/blockHelper.js b/tools/blockHelper.js deleted file mode 100644 index e47800652..000000000 --- a/tools/blockHelper.js +++ /dev/null @@ -1,207 +0,0 @@ -require( '../db.js' ); -var etherUnits = require("../lib/etherUnits.js"); -var BigNumber = require('bignumber.js'); - -var Web3 = require('web3'); - -var mongoose = require( 'mongoose' ); -var Block = mongoose.model( 'Block' ); -var Transaction = mongoose.model( 'Transaction' ); - -var grabBlocks = function(config) { - if('listenOnly' in config && config.listenOnly === true) - listenBlocks(config, web3); - else - setTimeout(function() { - grabBlock(config, web3, config.blocks.pop()); - }, 2000); -} - -var listenBlocks = function(config, web3) { - var newBlocks = web3.eth.filter("latest"); - newBlocks.watch(function (error, log) { - if(error) { - console.log('Error: ' + error); - } else if (log == null) { - console.log('Warning: null block hash'); - } else { - grabBlock(config, web3, log); - } - }); -} - -var grabBlock = function(config, web3, blockHashOrNumber) { - var desiredBlockHashOrNumber; - // check if done - if(blockHashOrNumber == undefined) { - return; - } - if (typeof blockHashOrNumber === 'object') { - if('start' in blockHashOrNumber && 'end' in blockHashOrNumber) { - desiredBlockHashOrNumber = blockHashOrNumber.end; - } - else { - console.log('Error: Aborted becasue found a interval in blocks ' + - 'array that doesn\'t have both a start and end.'); - process.exit(9); - } - } - else { - desiredBlockHashOrNumber = blockHashOrNumber; - } - if(web3.eth.net.isListening()) { - web3.eth.getBlock(desiredBlockHashOrNumber, true, function(error, blockData) { - if(error) { - console.log('Warning: error on getting block with hash/number: ' + - desiredBlockHashOrNumber + ': ' + error); - } - else if(blockData == null) { - console.log('Warning: null block data received from the block with hash/number: ' + - desiredBlockHashOrNumber); - } - else { - if('terminateAtExistingDB' in config && config.terminateAtExistingDB === true) { - checkBlockDBExistsThenWrite(config, blockData); - } - else { - writeBlockToDB(config, blockData); - } - if (!('skipTransactions' in config && config.skipTransactions === true)) - writeTransactionsToDB(config, blockData); - if('listenOnly' in config && config.listenOnly === true) - return; - - if('hash' in blockData && 'number' in blockData) { - // If currently working on an interval (typeof blockHashOrNumber === 'object') and - // the block number or block hash just grabbed isn't equal to the start yet: - // then grab the parent block number ( - 1). Otherwise done - // with this interval object (or not currently working on an interval) - // -> so move onto the next thing in the blocks array. - if(typeof blockHashOrNumber === 'object' && - ( - (typeof blockHashOrNumber['start'] === 'string' && blockData['hash'] !== blockHashOrNumber['start']) || - (typeof blockHashOrNumber['start'] === 'number' && blockData['number'] > blockHashOrNumber['start']) - ) - ) { - blockHashOrNumber['end'] = blockData['number'] - 1; - grabBlock(config, web3, blockHashOrNumber); - } - else { - grabBlock(config, web3, config.blocks.pop()); - } - } - else { - console.log('Error: No hash or number was found for block: ' + blockHashOrNumber); - process.exit(9); - } - } - }); - } - else { - console.log('Error: Aborted due to web3 is not connected when trying to ' + - 'get block ' + desiredBlockHashOrNumber); - process.exit(9); - } -} - -var writeBlockToDB = function(config, blockData) { - return new Block(blockData).save( function( err, block, count ){ - if ( typeof err !== 'undefined' && err ) { - if (err.code == 11000) { - console.log('Skip: Duplicate key ' + - blockData.number.toString() + ': ' + - err); - } else { - console.log('Error: Aborted due to error on ' + - 'block number ' + blockData.number.toString() + ': ' + - err); - process.exit(9); - } - } else { - if(!('quiet' in config && config.quiet === true)) { - console.log('DB successfully written for block number ' + - blockData.number.toString() ); - } - } - }); -} - -/** - * Checks if the a record exists for the block number then -> - * if record exists: abort - * if record DNE: write a file for the block - */ -var checkBlockDBExistsThenWrite = function(config, blockData) { - Block.find({number: blockData.number}, function (err, b) { - if (!b.length) - writeBlockToDB(config, blockData); - else { - console.log('Aborting because block number: ' + blockData.number.toString() + - ' already exists in DB.'); - process.exit(9); - } - - }) -} - -/** - Break transactions out of blocks and write to DB -**/ -var writeTransactionsToDB = function(config, blockData) { - var bulkOps = []; - if (blockData.transactions.length > 0) { - for (d in blockData.transactions) { - var txData = blockData.transactions[d]; - txData.timestamp = blockData.timestamp; - txData.value = etherUnits.toEther(new BigNumber(txData.value), 'wei'); - bulkOps.push(txData); - } - Transaction.collection.insert(bulkOps, function( err, tx ){ - if ( typeof err !== 'undefined' && err ) { - if (err.code == 11000) { - console.log('Skip: Duplicate key ' + - err); - } else { - console.log('Error: Aborted due to error: ' + - err); - process.exit(9); - } - } else if(!('quiet' in config && config.quiet === true)) { - console.log('DB successfully written for block ' + - blockData.transactions.length.toString() ); - } - }); - } -} - -// load config.json -var config = { nodeAddr: 'localhost', wsPort: 8546, 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); - } -} - -console.log('Connecting ' + config.nodeAddr + ':' + config.wsPort + '...'); - -var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://' + config.nodeAddr + ':' + config.wsPort.toString())); - -// set the default blocks if it's not provided -if (!('blocks' in config) || !(Array.isArray(config.blocks))) { - config.blocks = []; - config.blocks.push({'start': 0, 'end': 'latest'}); -} - -console.log('Using configuration:'); -console.log(config); - -grabBlocks(config); diff --git a/tools/patcher.js b/tools/patcher.js deleted file mode 100644 index b820aa61e..000000000 --- a/tools/patcher.js +++ /dev/null @@ -1,302 +0,0 @@ -require( '../db.js' ); -var etherUnits = require("../lib/etherUnits.js"); -var BigNumber = require('bignumber.js'); - -var Web3 = require('web3'); - -var mongoose = require( 'mongoose' ); -var Block = mongoose.model( 'Block' ); -var Transaction = mongoose.model( 'Transaction' ); -var Contract = mongoose.model( 'Contract' ); -var TokenTransfer = mongoose.model( 'TokenTransfer' ); - -const ERC20ABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]; -const ERC20_METHOD_DIC = {"0xa9059cbb":"transfer", "0xa978501e":"transferFrom"}; -const METHOD_DIC = { - "0x930a61a57a70a73c2a503615b87e2e54fe5b9cdeacda518270b852296ab1a377":"Transfer(address,address,uint)", - "0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b":"transfer(address,uint256)", - "0xa978501e4506ecbd340f6e45a48ac5bd126b1c14f03f2210837c8e0b602d4d7b":"transferFrom(address,address,uint)", - "0x086c40f692cc9c13988b9e49a7610f67375e8373bfe7653911770b351c2b1c54":"approve(address,uint)", - "0xf2fde38b092330466c661fc723d5289b90272a3e580e3187d1d7ef788506c557":"transferOwnership(address)", - "0x3bc50cfd0fe2c05fb67c0fe4be91fb10eb723ba30ea8f559d533fcd5fe29be7f":"Released(address,uint)", - "0xb21fb52d5749b80f3182f8c6992236b5e5576681880914484d7f4c9b062e619e":"Released(address indexed, uint indexed)" -}; - -const normalizeTX = async (txData, receipt, blockData) => { - var tx = { - blockHash: txData.blockHash, - blockNumber: txData.blockNumber, - from: txData.from.toLowerCase(), - hash: txData.hash.toLowerCase(), - value: etherUnits.toEther(new BigNumber(txData.value), 'wei'), - nonce: txData.nonce, - r: txData.r, - s: txData.s, - v: txData.v, - gas: txData.gas, - gasUsed: receipt.gasUsed, - gasPrice: String(txData.gasPrice), - input: txData.input, - transactionIndex: txData.transactionIndex, - timestamp: blockData.timestamp - }; - - if (receipt.status) - tx.status = receipt.status; - - if (txData.to) { - tx.to = txData.to.toLowerCase(); - return tx; - } else { - if (tx.creates) { - tx.creates = txData.creates.toLowerCase(); - return tx; - } else { - if (receipt && receipt.contractAddress) { - tx.creates = receipt.contractAddress.toLowerCase(); - } - return tx; - } - } -} - -var grabBlock = function(config, web3, blockHashOrNumber) { - var desiredBlockHashOrNumber; - // check if done - if(blockHashOrNumber == undefined) { - return; - } - desiredBlockHashOrNumber = blockHashOrNumber; - if(web3.eth.net.isListening()) { - web3.eth.getBlock(desiredBlockHashOrNumber, true, function(error, blockData) { - if(error) { - console.log('Warning: error on getting block with hash/number: ' + - desiredBlockHashOrNumber + ': ' + error); - } - else if(blockData == null) { - console.log('Warning: null block data received from the block with hash/number: ' + - desiredBlockHashOrNumber); - } - else { - checkBlockDBExistsThenWrite(config, blockData); - } - }); - } - else { - console.log('Error: Aborted due to web3 is not connected when trying to ' + - 'get block ' + desiredBlockHashOrNumber); - process.exit(9); - } -} -var writeBlockToDB = function(config, blockData) { - return new Block(blockData).save( function( err, block, count ){ - if ( typeof err !== 'undefined' && err ) { - if (err.code == 11000) { - console.log('Skip: Duplicate DB on #' + blockData.number.toString()); - } else { - console.log('Error: Aborted due to error on ' + - 'block number ' + blockData.number.toString() + ': ' + - err); - process.exit(9); - } - } else { - if(!('quiet' in config && config.quiet === true)) { - console.log('DB successfully written for block #' + - blockData.number.toString() ); - } - } - }); -} - -/** - * Checks if the a record exists for the block number then -> - * if record exists: abort - * if record DNE: write a file for the block - */ -var checkBlockDBExistsThenWrite = function(config, blockData) { - Block.find({number: blockData.number}, function (err, b) { - if (!b.length) { - writeBlockToDB(config, blockData); - writeTransactionsToDB(config, blockData); - } else { - console.log('Block #' + blockData.number.toString() + ' already exists in DB.'); - } - - }) -} - -/** - Break transactions out of blocks and write to DB -**/ -const writeTransactionsToDB = async(config, blockData) => { - var bulkOps = []; - if (blockData.transactions.length > 0) { - for (d in blockData.transactions) { - var txData = blockData.transactions[d]; - var receipt = await web3.eth.getTransactionReceipt(txData.hash); - var tx = await normalizeTX(txData, receipt, blockData); - // Contact creation tx, Event logs of internal transaction - if (txData.input && txData.input.length > 2) { - // Contact creation tx - if (txData.to == null) { - contractAddress = txData.creates.toLowerCase(); - var contractdb = {} - var isTokenContract = true; - var Token = new web3.eth.Contract(ERC20ABI, contractAddress); - contractdb.owner = txData.from; - contractdb.blockNumber = blockData.number; - contractdb.creationTransaction = txData.hash; - try { - var call = await web3.eth.call({ to: contractAddress, data:web3.utils.sha3("totalSupply()")}); - if (call == '0x') { - isTokenContract = false; - } else { - try { - contractdb.tokenName = await Token.methods.name().call(); - contractdb.decimals = await Token.methods.decimals().call(); - contractdb.symbol = await Token.methods.symbol().call(); - contractdb.totalSupply = await Token.methods.totalSupply().call(); - } catch (err) { - isTokenContract = false; - } - } - } catch (err) { - isTokenContract = false; - } - contractdb.byteCode = await web3.eth.getCode(contractAddress); - if (isTokenContract) { - contractdb.ERC = 2; - } else { - // Normal Contract - contractdb.ERC = 0; - } - // Write to db - Contract.update ( - {address: contractAddress}, - {$setOnInsert: contractdb}, - {upsert: true}, - function (err, data) { - if (err) { - console.log(err); - } - } - ); - } else { - // Internal transaction . write to doc of InternalTx - var transfer = {"blockNumber": "", "number": 0, "from": "", "to": "", "contract":"", "value": 0, "timestamp":0}; - var methodCode = txData.input.substr(0,10); - if (ERC20_METHOD_DIC[methodCode]=="transfer" || ERC20_METHOD_DIC[methodCode]=="transferFrom") { - if (ERC20_METHOD_DIC[methodCode]=="transfer") { - // Token transfer transaction - transfer.from = txData.from; - transfer.to = "0x" + txData.input.substring(34,74); - transfer.value = Number("0x" + txData.input.substring(74)); - } else { - // transferFrom - transfer.from = "0x" + txData.input.substring(34,74); - transfer.to = "0x" + txData.input.substring(74,114); - transfer.value = Number("0x" + txData.input.substring(114)); - } - transfer.method = ERC20_METHOD_DIC[methodCode]; - transfer.hash = txData.hash; - transfer.blockNumber = blockData.number; - transfer.contract = txData.to; - transfer.timestamp = blockData.timestamp; - // Write transfer transaction into db - TokenTransfer.update ( - {hash: transfer.hash}, - {$setOnInsert: transfer}, - {upsert: true}, - function (err, data) { - if (err) { - console.log(err); - } - } - ); - } - } - } - bulkOps.push(tx); - } - Transaction.collection.insert(bulkOps, function( err, tx ){ - if ( typeof err !== 'undefined' && err ) { - if (err.code == 11000) { - console.log('Skip: Duplicate transaction on #' + blockData.number.toString()); - } else { - console.log('Error: Aborted due to error: ' + - err); - process.exit(9); - } - } else if(!('quiet' in config && config.quiet === true)) { - console.log('DB successfully written for block ' + - blockData.transactions.length.toString() ); - - } - }); - } -} - -/* - Patch Missing Blocks -*/ -var patchBlocks = function(config) { - // number of blocks should equal difference in block numbers - var firstBlock = 0; - var lastBlock = web3.eth.getBlockNumber() - 1; - blockIter(web3, firstBlock, lastBlock, config); -} - -var blockIter = function(web3, firstBlock, lastBlock, config) { - // if consecutive, deal with it - if (lastBlock < firstBlock) - return; - if (lastBlock - firstBlock === 1) { - [lastBlock, firstBlock].forEach(function(blockNumber) { - Block.find({number: blockNumber}, function (err, b) { - if (!b.length) - grabBlock(config, web3, blockNumber); - }); - }); - } else if (lastBlock === firstBlock) { - Block.find({number: firstBlock}, function (err, b) { - if (!b.length) - grabBlock(config, web3, firstBlock); - }); - } else { - Block.count({number: {$gte: firstBlock, $lte: lastBlock}}, function(err, c) { - var expectedBlocks = lastBlock - firstBlock + 1; - console.log(" - expectedBlocks = " + expectedBlocks + ", real counting = " + c); - if (c === 0) { - console.log("INFO: No blocks found.") - } else if (expectedBlocks > c) { - console.log("* " + JSON.stringify(expectedBlocks - c) + " missing blocks found, between #" + firstBlock + " and #" + lastBlock); - var midBlock = firstBlock + parseInt((lastBlock - firstBlock)/2); - blockIter(web3, firstBlock, midBlock, config); - blockIter(web3, midBlock + 1, lastBlock, config); - } else - return; - }) - } -} - -// load config.json -var config = { nodeAddr: 'localhost', wsPort: 8546 }; -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); - } -} - -console.log('Connecting ' + config.nodeAddr + ':' + config.wsPort + '...'); -var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://' + config.nodeAddr + ':' + config.wsPort.toString())); - -patchBlocks(config); diff --git a/tools/price.js b/tools/price.js deleted file mode 100644 index f1f6516d9..000000000 --- a/tools/price.js +++ /dev/null @@ -1,60 +0,0 @@ -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://min-api.cryptocompare.com/data/price?fsym=${config.settings.symbol}&tsyms=USD`; - - try { - let requestUSD = await fetch(URL); - let quoteUSD = await requestUSD.json(); - console.log(quoteUSD) - - quoteObject = { - timestamp: Math.round( Date.now() / 1000), - quoteUSD: quoteUSD.USD, - } - - 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', wsPort: 8546, 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); diff --git a/tools/sync.js b/tools/sync.js index 4c205d4a0..c2a4b9d9c 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -12,6 +12,9 @@ var _ = require('lodash'); var asyncL = require('async'); var Web3 = require('web3'); +const fetch = require("node-fetch"); +const Market = require( '../db.js' ).Market; + var mongoose = require( 'mongoose' ); var Block = mongoose.model( 'Block' ); var Transaction = mongoose.model( 'Transaction' ); @@ -495,6 +498,43 @@ var checkBlockDBExistsThenWrite = function(config, patchData, flush) { } }); }; +/** + Fetch market price from cryptocompare +**/ +// 10 minutes +const quoteInterval = 10 * 60 * 1000; + +const getQuote = async () => { + const options = { + timeout: 10000 + } + const URL = `https://min-api.cryptocompare.com/data/price?fsym=${config.settings.symbol}&tsyms=USD`; + + try { + let requestUSD = await fetch(URL); + let quoteUSD = await requestUSD.json(); + + quoteObject = { + timestamp: Math.round( Date.now() / 1000), + quoteUSD: quoteUSD.USD, + } + + new Market(quoteObject).save( ( err, market, count ) => { + if ( typeof err !== 'undefined' && err ) { + process.exit(9); + } else { + if(!('quiet' in config && config.quiet === true)) { + console.log('DB successfully written for market quote.'); + } + } + }); + } catch (error) { + if(!('quiet' in config && config.quiet === true)) { + console.log(error); + } + } +} + /** Start config for node connection and sync **/ @@ -545,3 +585,10 @@ if (config.syncAll === true){ console.log('Starting Full Sync'); syncChain(config); } + +// Start price sync on DB +getQuote() + +setInterval(() => { + getQuote() +}, quoteInterval); From 5e85107313c79165434663d1237bd229e754a71e Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 06:41:40 +0900 Subject: [PATCH 24/46] cleanup: fix travis --- .travis.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 153f46347..c28c225ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ services: - docker before_install: - docker pull trufflesuite/ganache-cli - - docker run -d -p 8546:8546 -p 27017:27017 trufflesuite/ganache-cli + - docker run -d -p 8546:8546 -p 27017:27017 trufflesuite/ganache-cli -p 8546 - varA=`docker ps --no-trunc -q | cut -c 1-12` - docker pull mongo - docker run -d --network="container:$varA" mongo diff --git a/package.json b/package.json index 6b7a5cd76..60244dbf2 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "node-fetch": "^2.3.0", "rlp": "^2.2.3", "serve-favicon": "~2.5.0", - "solc": "^0.4.19", + "solc": "^0.5.6", "web3": "1.0.0-beta.37", "web3-explorer": "1.0.2" }, From a3f8f7376218528fb0393040e61296005da34397 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 07:01:57 +0900 Subject: [PATCH 25/46] cleanup: more cleanup * remove dead code ( web3dummy ) * remove duplicated app.js file --- app/app.js | 87 --------------------------------------------- package.json | 2 -- routes/compiler.js | 3 -- routes/web3dummy.js | 65 --------------------------------- routes/web3relay.js | 6 +--- 5 files changed, 1 insertion(+), 162 deletions(-) delete mode 100644 app/app.js delete mode 100644 routes/web3dummy.js diff --git a/app/app.js b/app/app.js deleted file mode 100644 index b2e4ba899..000000000 --- a/app/app.js +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env node - -require( './db' ); - -var express = require('express'); -var path = require('path'); -var favicon = require('serve-favicon'); -var logger = require('morgan'); -var bodyParser = require('body-parser'); - -var config = {}; -try { - config = require('./config.json'); -} catch(e) { - if (e.code == 'MODULE_NOT_FOUND') { - console.log('No config file found. Using default configuration... (tools/config.json)'); - config = require('./tools/config.json'); - } else { - throw e; - process.exit(1); - } -} - -var app = express(); -app.set('port', process.env.PORT || 3000); - -// view engine setup -app.set('views', path.join(__dirname, 'views')); -app.set('view engine', 'ejs'); - -app.use(favicon(__dirname + '/public/favicon.ico')); -app.use(logger('dev')); -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: true })); -app.use(express.static(path.join(__dirname, 'public'))); - -// app libraries -global.__lib = __dirname + '/lib/'; - - -// client - -app.get('/', function(req, res) { - res.render('index', config); -}); - -app.get('/config', function(req, res) { - res.json(config.settings); -}); - -require('./routes')(app); - -// let angular catch them -app.use(function(req, res) { - res.render('index', config); -}); - -// error handlers - -// development error handler -// will print stacktrace -if (app.get('env') === 'development') { - app.use(function(err, req, res, next) { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: err - }); - }); -} - - -// production error handler -// no stacktraces leaked to user -app.use(function(err, req, res, next) { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: {} - }); -}); - -var http = require('http').Server(app); - -http.listen(app.get('port'), '0.0.0.0', function() { - console.log('Express server listening on port ' + app.get('port')); -}); diff --git a/package.json b/package.json index 60244dbf2..566fc6b05 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "sync": "node tools/sync.js", "stats": "node tools/stats.js", "rich": "node tools/richlist.js", - "pretest": "copyfiles app.js app/ ", "test": "mocha --exit" }, "dependencies": { @@ -30,7 +29,6 @@ }, "devDependencies": { "chai": "^4.2.0", - "copyfiles": "^2.1.0", "ganache-cli": "^6.4.1", "mocha": "^6.0.2", "request": "^2.88.0" diff --git a/routes/compiler.js b/routes/compiler.js index 5eaedf830..113ad42a2 100644 --- a/routes/compiler.js +++ b/routes/compiler.js @@ -1,8 +1,5 @@ var solc = require('solc'); - -// var eth = require('./web3dummy').eth; var eth = require('./web3relay').eth; - var Contract = require('./contracts'); /* diff --git a/routes/web3dummy.js b/routes/web3dummy.js deleted file mode 100644 index 9cc7a56ae..000000000 --- a/routes/web3dummy.js +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env node - -/* - Stand-in for local testing of web3 calls -*/ -var BigNumber = require('bignumber.js'); -var etherUnits = require(__lib + "etherUnits.js") - -exports.data = function(req, res){ - console.log(req.body) - - if ("addr" in req.body) { - var addr = req.body.addr.toLowerCase(); - var options = req.body.options; - var web3Tasks = []; - - var addrData = {}; - - if (options.indexOf("balance") > -1) { - addrData["balance"] = new BigNumber(75380000001024); - addrData["balance"] = etherUnits.toEther(addrData["balance"], 'wei'); - } - if (options.indexOf("count") > -1) { - addrData["count"] = 139; - } - if (options.indexOf("bytecode") > -1) { - addrData["isContract"] = true; - addrData["bytecode"] = "0x606060405273da4a4626d3e16e094de3225a751aab7128e96526600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550610462806100516000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e6e504a1461005a5780633ccfd60b14610069578063eedcf50a14610078578063fdf97cb2146100b157610058565b005b61006760048050506100ea565b005b6100766004805050610277565b005b6100856004805050610424565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100be600480505061043c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166318160ddd604051817c01000000000000000000000000000000000000000000000000000000000281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166370a0823130604051827c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303816000876161da5a03f11561000257505050604051805190602001503073ffffffffffffffffffffffffffffffffffffffff16310103604051809050600060405180830381858888f19350505050505b565b600073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166370a0823133604051827c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303816000876161da5a03f1156100025750505060405180519060200150905073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166323b872dd333084604051847c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200193505050506020604051808303816000876161da5a03f1156100025750505060405180519060200150158061041657503373ffffffffffffffffffffffffffffffffffffffff16600082604051809050600060405180830381858888f19350505050155b1561042057610002565b5b50565b73bb9bc244d798123fde783fcc1c72d3bb8c18941381565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156"; - } - - res.write(JSON.stringify(addrData)); - res.end(); - - - } else if ("tx" in req.body) { - var tx = { - blockHash: "0x59fee9b288d1201841ca59569026a93fa0e32f350224019747145cc52d2877ba", - blockNumber: 2004907, - from: "0xf9436cd1bc93805bd54326dbb8857e15e9e5ef4a", - gas: 90000, - gasPrice: 20000000000, - hash: "0x3868a24286d737841f42c55384b5593111defccfcec4a2d0b38115d67b10af6c", - input: "0x", - nonce: 3042, - to: "0x7172e090ef7aad8fb5b58052040587aaf248d7be", - transactionIndex: 5, - value: etherUnits.toEther( new BigNumber("400000000000000000000"), "wei") - } - - res.write(JSON.stringify(tx)); - res.end(); - - } else { - - console.error("Invalid Request: " + action) - res.status(400).send(); - } - -}; - -exports.eth = new function() { - this.getCode = function(addr) { - return "0x606060405273da4a4626d3e16e094de3225a751aab7128e96526600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550610462806100516000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e6e504a1461005a5780633ccfd60b14610069578063eedcf50a14610078578063fdf97cb2146100b157610058565b005b61006760048050506100ea565b005b6100766004805050610277565b005b6100856004805050610424565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100be600480505061043c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166318160ddd604051817c01000000000000000000000000000000000000000000000000000000000281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166370a0823130604051827c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303816000876161da5a03f11561000257505050604051805190602001503073ffffffffffffffffffffffffffffffffffffffff16310103604051809050600060405180830381858888f19350505050505b565b600073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166370a0823133604051827c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303816000876161da5a03f1156100025750505060405180519060200150905073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166323b872dd333084604051847c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200193505050506020604051808303816000876161da5a03f1156100025750505060405180519060200150158061041657503373ffffffffffffffffffffffffffffffffffffffff16600082604051809050600060405180830381858888f19350505050155b1561042057610002565b5b50565b73bb9bc244d798123fde783fcc1c72d3bb8c18941381565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156"; - } -} diff --git a/routes/web3relay.js b/routes/web3relay.js index 46449166d..38c3c5a13 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -42,11 +42,7 @@ try { //Create Web3 connection console.log('Connecting ' + config.nodeAddr + ':' + config.wsPort + '...'); -if (typeof web3 !== "undefined") { - web3 = new Web3(web3.currentProvider); -} else { - web3 = new Web3(new Web3.providers.WebsocketProvider('ws://' + config.nodeAddr +':'+ config.wsPort)); -} +web3 = new Web3(new Web3.providers.WebsocketProvider('ws://' + config.nodeAddr +':'+ config.wsPort)); if (web3.eth.net.isListening()) console.log("Web3 connection established"); From fb9e48d4875d36f2ed11e492fadecbb1c6f62b9e Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 07:06:48 +0900 Subject: [PATCH 26/46] cleanup: remove ganache-cli from node deps not being used since it has its docker running --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 566fc6b05..00212f897 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ }, "devDependencies": { "chai": "^4.2.0", - "ganache-cli": "^6.4.1", "mocha": "^6.0.2", "request": "^2.88.0" } From 32ff5895615c1b64a1ec02d2f66e1e311d7f04da Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 07:20:21 +0900 Subject: [PATCH 27/46] cleanup: add package-lock.json --- package-lock.json | 5051 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 5051 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..1a0910681 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5051 @@ +{ + "name": "etc-explorer", + "version": "0.2.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "10.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.1.tgz", + "integrity": "sha512-Rymt08vh1GaW4vYB6QP61/5m/CFLGnFZP++bJpWbiNxceNa6RBipDmb413jvtSf/R1gg5a/jQVl2jY4XVRscEA==" + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" + }, + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "^4.14.0" + } + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bignumber.js": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-8.1.1.tgz", + "integrity": "sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sha3": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.4.tgz", + "integrity": "sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY=", + "requires": { + "js-sha3": "^0.6.1", + "safe-buffer": "^5.1.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "bson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, + "buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "command-exists": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", + "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==" + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concurrently": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-4.1.0.tgz", + "integrity": "sha512-pwzXCE7qtOB346LyO9eFWpkFJVO3JQZ/qU/feGeaAHiX1M3Rw3zgXKc5cZ8vSH5DGygkjzLFDzA/pwoQDkRNGg==", + "requires": { + "chalk": "^2.4.1", + "date-fns": "^1.23.0", + "lodash": "^4.17.10", + "read-pkg": "^4.0.1", + "rxjs": "^6.3.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^4.5.0", + "tree-kill": "^1.1.0", + "yargs": "^12.0.1" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", + "requires": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + }, + "dependencies": { + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + } + } + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "keccakjs": "^0.2.1", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" + } + }, + "ethers": { + "version": "4.0.0-beta.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.1.tgz", + "integrity": "sha512-SoYhktEbLxf+fiux5SfCEwdzWENMvgIbMZD90I62s4GZD9nEjgEWy8ZboI3hck193Vs0bDoTohDISx84f2H2tw==", + "requires": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + }, + "setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + } + } + }, + "ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "requires": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "fs-promise": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-2.0.3.tgz", + "integrity": "sha1-9k5PhUvPaJqovdy6JokW2z20aFQ=", + "requires": { + "any-promise": "^1.3.0", + "fs-extra": "^2.0.0", + "mz": "^2.6.0", + "thenify-all": "^1.6.0" + }, + "dependencies": { + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hooks-fixed": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.2.tgz", + "integrity": "sha512-YurCM4gQSetcrhwEtpQHhQ4M7Zo7poNGqY4kQGeBS6eZtOcT3tnNs01ThFa0jYBByAiYt1MjMjP/YApG0EnAvQ==" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "requires": { + "punycode": "2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" + } + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, + "js-sha3": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.6.1.tgz", + "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA=" + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kareem": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", + "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" + }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, + "keccakjs": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.3.tgz", + "integrity": "sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg==", + "requires": { + "browserify-sha3": "^0.0.4", + "sha3": "^1.2.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", + "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "requires": { + "mime-db": "~1.38.0" + } + }, + "mimic-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", + "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "^0.1.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "requires": { + "mkdirp": "*" + } + }, + "mocha": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.0.2.tgz", + "integrity": "sha512-RtTJsmmToGyeTznSOMoM6TPEk1A84FQaHIciKrRqARZx+B5ccJ5tXlmJzEKGBxZdqk9UjpRsesZTUkZmR5YnuQ==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "findup-sync": "2.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.12.0", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.4", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "12.0.5", + "yargs-parser": "11.1.1", + "yargs-unparser": "1.5.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "mock-fs": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.8.0.tgz", + "integrity": "sha512-Gwj4KnJOW15YeTJKO5frFd/WDO5Mc0zxXqL9oHx3+e9rBqW8EVARqQHSaIXznUdljrD6pvbNGW2ZGXKPEfYJfw==" + }, + "mongodb": { + "version": "2.2.34", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.34.tgz", + "integrity": "sha1-o09Zu+thdUrsQy3nLD/iFSakTBo=", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.18", + "readable-stream": "2.2.7" + } + }, + "mongodb-core": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz", + "integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=", + "requires": { + "bson": "~1.0.4", + "require_optional": "~1.0.0" + } + }, + "mongoose": { + "version": "4.13.18", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.13.18.tgz", + "integrity": "sha512-pPZlVID+/9xl0pyBibr7CZbjYKzpJZuw58TdWwIxr3ydO/OUZqhX1kUEAQIzsOJVSsL6GnD1fb54reO35jvLtw==", + "requires": { + "async": "2.6.0", + "bson": "~1.0.4", + "hooks-fixed": "2.0.2", + "kareem": "1.5.0", + "lodash.get": "4.4.2", + "mongodb": "2.2.34", + "mpath": "0.5.1", + "mpromise": "0.5.5", + "mquery": "2.3.3", + "ms": "2.0.0", + "muri": "1.3.0", + "regexp-clone": "0.0.1", + "sliced": "1.0.1" + } + }, + "morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "requires": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + } + }, + "mout": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", + "integrity": "sha1-ujYR318OWx/7/QEWa48C0fX6K5k=" + }, + "mpath": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.1.tgz", + "integrity": "sha512-H8OVQ+QEz82sch4wbODFOz+3YQ61FYz/z3eJ5pIdbMEaUzDqA268Wd+Vt4Paw9TJfvDgVKaayC0gBzMIw2jhsg==" + }, + "mpromise": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz", + "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" + }, + "mquery": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.3.tgz", + "integrity": "sha512-NC8L14kn+qxJbbJ1gbcEMDxF0sC3sv+1cbRReXXwVvowcwY1y9KoVZFq0ebwARibsadu8lx8nWGvm3V0Pf0ZWQ==", + "requires": { + "bluebird": "3.5.0", + "debug": "2.6.9", + "regexp-clone": "0.0.1", + "sliced": "0.0.5" + }, + "dependencies": { + "sliced": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", + "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "muri": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/muri/-/muri-1.3.0.tgz", + "integrity": "sha512-FiaFwKl864onHFFUV/a2szAl7X0fxVlSKNdhTf+BM8i8goEgYut8u5P9MqQqIYwvaMxjzVESsoEm/2kfkFH1rg==" + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "nan": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz", + "integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==" + }, + "nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node-environment-flags": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.4.tgz", + "integrity": "sha512-M9rwCnWVLW7PX+NUWe3ejEdiLYinRpsEre9hMkU/6NS4h+EEulYaDH1gCEZ2gyXsmw+RXYDaV2JkkTNcsPDJ0Q==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "node-fetch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", + "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "requires": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "oboe": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", + "integrity": "sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8=", + "requires": { + "http-https": "^1.0.0" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==" + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "^1.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==" + }, + "parse-asn1": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-headers": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.2.tgz", + "integrity": "sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg==", + "requires": { + "for-each": "^0.3.3", + "string.prototype.trim": "^1.1.2" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "randomhex": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", + "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "requires": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + } + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp-clone": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", + "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.3.tgz", + "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", + "requires": { + "bn.js": "^4.11.1", + "safe-buffer": "^5.1.1" + } + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "requires": { + "nan": "^2.0.8" + } + }, + "scrypt-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" + }, + "scrypt.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", + "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", + "requires": { + "scrypt": "^6.0.2", + "scryptsy": "^1.2.1" + } + }, + "scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "requires": { + "pbkdf2": "^3.0.3" + } + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "requires": { + "commander": "~2.8.1" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "serve-favicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", + "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=", + "requires": { + "etag": "~1.8.1", + "fresh": "0.5.2", + "ms": "2.1.1", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "requires": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "sha3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", + "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", + "requires": { + "nan": "2.10.0" + }, + "dependencies": { + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "solc": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.5.6.tgz", + "integrity": "sha512-BuvrLwOSAGEUbE4jffLBcO9Vm8OVgxImE5qFTHzjH2n+RqBHeqDDOY0gU4LvGWsA6ttjADJyRriF9Pp0vjIq2g==", + "requires": { + "command-exists": "^1.2.8", + "fs-extra": "^0.30.0", + "keccak": "^1.0.2", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33", + "yargs": "^11.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=" + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "requires": { + "has-flag": "^2.0.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + } + } + }, + "swarm-js": { + "version": "0.1.37", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.37.tgz", + "integrity": "sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ==", + "requires": { + "bluebird": "^3.5.0", + "buffer": "^5.0.5", + "decompress": "^4.0.0", + "eth-lib": "^0.1.26", + "fs-extra": "^2.1.2", + "fs-promise": "^2.0.0", + "got": "^7.1.0", + "mime-types": "^2.1.16", + "mkdirp-promise": "^5.0.1", + "mock-fs": "^4.1.0", + "setimmediate": "^1.0.5", + "tar.gz": "^1.0.5", + "xhr-request-promise": "^0.1.2" + }, + "dependencies": { + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0" + } + } + } + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "tar.gz": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tar.gz/-/tar.gz-1.0.7.tgz", + "integrity": "sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg==", + "requires": { + "bluebird": "^2.9.34", + "commander": "^2.8.1", + "fstream": "^1.0.8", + "mout": "^0.11.0", + "tar": "^2.1.1" + }, + "dependencies": { + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + } + } + }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==" + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "unbzip2-stream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", + "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "^1.0.1" + } + }, + "url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "web3": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.0.0-beta.37.tgz", + "integrity": "sha512-8XLgUspdzicC/xHG82TLrcF/Fxzj2XYNJ1KTYnepOI77bj5rvpsxxwHYBWQ6/JOjk0HkZqoBfnXWgcIHCDhZhQ==", + "requires": { + "web3-bzz": "1.0.0-beta.37", + "web3-core": "1.0.0-beta.37", + "web3-eth": "1.0.0-beta.37", + "web3-eth-personal": "1.0.0-beta.37", + "web3-net": "1.0.0-beta.37", + "web3-shh": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-bzz": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.0.0-beta.37.tgz", + "integrity": "sha512-E+dho49Nsm/QpQvYWOF35YDsQrMvLB19AApENxhlQsu6HpWQt534DQul0t3Y/aAh8rlKD6Kanxt8LhHDG3vejQ==", + "requires": { + "got": "7.1.0", + "swarm-js": "0.1.37", + "underscore": "1.8.3" + } + }, + "web3-core": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.37.tgz", + "integrity": "sha512-cIwEqCj7OJyefQNauI0HOgW4sSaOQ98V99H2/HEIlnCZylsDzfw7gtQUdwnRFiIyIxjbWy3iWsjwDPoXNPZBYg==", + "requires": { + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-core-requestmanager": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.37.tgz", + "integrity": "sha512-efaLOzN28RMnbugnyelgLwPWWaSwElQzcAJ/x3PZu+uPloM/lE5x0YuBKvIh7/PoSMlHqtRWj1B8CpuQOUQ5Ew==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.37.tgz", + "integrity": "sha512-pKWFUeqnVmzx3VrZg+CseSdrl/Yrk2ioid/HzolNXZE6zdoITZL0uRjnsbqXGEzgRRd1Oe/pFndpTlRsnxXloA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-promievent": "1.0.0-beta.37", + "web3-core-subscriptions": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.37.tgz", + "integrity": "sha512-GTF2r1lP8nJBeA5Gxq5yZpJy9l8Fb9CXGZPfF8jHvaRdQHtm2Z+NDhqYmF833lcdkokRSyfPcXlz1mlWeClFpg==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.37.tgz", + "integrity": "sha512-66VUqye5BGp1Zz1r8psCxdNH+GtTjaFwroum2Osx+wbC5oRjAiXkkadiitf6wRb+edodjEMPn49u7B6WGNuewQ==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37", + "web3-providers-http": "1.0.0-beta.37", + "web3-providers-ipc": "1.0.0-beta.37", + "web3-providers-ws": "1.0.0-beta.37" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.37.tgz", + "integrity": "sha512-FdXl8so9kwkRRWziuCSpFsAuAdg9KvpXa1fQlT16uoGcYYfxwFO/nkwyBGQzkZt7emShI2IRugcazyPCZDwkOA==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37" + } + }, + "web3-eth": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.0.0-beta.37.tgz", + "integrity": "sha512-Eb3aGtkz3G9q+Z9DKgSQNbn/u8RtcZQQ0R4sW9hy5KK47GoT6vab5c6DiD3QWzI0BzitHzR5Ji+3VHf/hPUGgw==", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-core-subscriptions": "1.0.0-beta.37", + "web3-eth-abi": "1.0.0-beta.37", + "web3-eth-accounts": "1.0.0-beta.37", + "web3-eth-contract": "1.0.0-beta.37", + "web3-eth-ens": "1.0.0-beta.37", + "web3-eth-iban": "1.0.0-beta.37", + "web3-eth-personal": "1.0.0-beta.37", + "web3-net": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.37.tgz", + "integrity": "sha512-g9DKZGM2OqwKp/tX3W/yihcj7mQCtJ6CXyZXEIZfuDyRBED/iSEIFfieDOd+yo16sokLMig6FG7ADhhu+19hdA==", + "requires": { + "ethers": "4.0.0-beta.1", + "underscore": "1.8.3", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-eth-accounts": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.37.tgz", + "integrity": "sha512-uvbHL62/zwo4GDmwKdqH9c/EgYd8QVnAfpVw8D3epSISpgbONNY7Hr4MRMSd/CqAP12l2Ls9JVQGLhhC83bW6g==", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scrypt.js": "0.2.0", + "underscore": "1.8.3", + "uuid": "2.0.1", + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + }, + "dependencies": { + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + } + } + }, + "web3-eth-contract": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.37.tgz", + "integrity": "sha512-h1B3A8Z/C7BlnTCHkrWbXZQTViDxfR12lKMeTkT8Sqj5phFmxrBlPE4ORy4lf1Dk5b23mZYE0r/IRACx4ThCrQ==", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-core-promievent": "1.0.0-beta.37", + "web3-core-subscriptions": "1.0.0-beta.37", + "web3-eth-abi": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-eth-ens": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.37.tgz", + "integrity": "sha512-dR3UkrVzdRrJhfP57xBPx0CMiVnCcYFvh+u2XMkGydrhHgupSUkjqGr89xry/j1T0BkuN9mikpbyhdCVMXqMbg==", + "requires": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-promievent": "1.0.0-beta.37", + "web3-eth-abi": "1.0.0-beta.37", + "web3-eth-contract": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.37.tgz", + "integrity": "sha512-WQRniGJFxH/XCbd7miO6+jnUG+6bvuzfeufPIiOtCbeIC1ypp1kSqER8YVBDrTyinU1xnf1U5v0KBZ2yiWBJxQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.37" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "web3-eth-personal": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.37.tgz", + "integrity": "sha512-B4dZpGbD+nGnn48i6nJBqrQ+HB7oDmd+Q3wGRKOsHSK5HRWO/KwYeA7wgwamMAElkut50lIsT9EJl4Apfk3G5Q==", + "requires": { + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-net": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-explorer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/web3-explorer/-/web3-explorer-1.0.2.tgz", + "integrity": "sha512-CeaUVJVJBxX8nyblgchEo6EIl8snf+pq26vimiEz12IHvO2wTYXKWYH6fC3m3Mkp+fsdCQ6O24KIo8x92jO54w==" + }, + "web3-net": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.0.0-beta.37.tgz", + "integrity": "sha512-xG/uBtMdDa1UMXw9KjDUgf3fXA/fDEJUYUS0TDn+U9PMgngA+UVECHNNvQTrVVDxEky38V3sahwIDiopNsQdsw==", + "requires": { + "web3-core": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.37.tgz", + "integrity": "sha512-FM/1YDB1jtZuTo78habFj7S9tNHoqt0UipdyoQV29b8LkGKZV9Vs3is8L24hzuj1j/tbwkcAH+ewIseHwu0DTg==", + "requires": { + "web3-core-helpers": "1.0.0-beta.37", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.37.tgz", + "integrity": "sha512-NdRPRxYMIU0C3u18NI8u4bwbhI9pCg5nRgDGYcmSAx5uOBxiYcQy+hb0WkJRRhBoyIXJmy+s26FoH8904+UnPg==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.37.tgz", + "integrity": "sha512-8p6ZLv+1JYa5Vs8oBn33Nn3VGFBbF+wVfO+b78RJS1Qf1uIOzjFVDk3XwYDD7rlz9G5BKpxhaQw+6EGQ7L02aw==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-shh": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.0.0-beta.37.tgz", + "integrity": "sha512-h5STG/xqZNQWtCLYOu7NiMqwqPea8SfkKQUPUFxXKIPVCFVKpHuQEwW1qcPQRJMLhlQIv17xuoUe1A+RzDNbrw==", + "requires": { + "web3-core": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-core-subscriptions": "1.0.0-beta.37", + "web3-net": "1.0.0-beta.37" + } + }, + "web3-utils": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.37.tgz", + "integrity": "sha512-kA1fyhO8nKgU21wi30oJQ/ssvu+9srMdjOTKbHYbQe4ATPcr5YNwwrxG3Bcpbu1bEwRUVKHCkqi+wTvcAWBdlQ==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible", + "requires": { + "debug": "^2.2.0", + "nan": "^2.3.3", + "typedarray-to-buffer": "^3.1.2", + "yaeti": "^0.0.6" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "requires": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "requires": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "xhr-request-promise": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz", + "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", + "requires": { + "xhr-request": "^1.0.1" + } + }, + "xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", + "requires": { + "cookiejar": "^2.1.1" + } + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} From 5f17c6039ae11b97d8dfca1cde09a8dbdadacf99 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 08:45:18 +0900 Subject: [PATCH 28/46] cleanup: fix leftover useFiat settings --- routes/web3relay.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/routes/web3relay.js b/routes/web3relay.js index 38c3c5a13..47cfc6ef6 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -129,11 +129,9 @@ exports.data = async (req, res) => { txResponse.gasPriceEther = etherUnits.toEther( new BigNumber(txResponse.gasPrice), "wei"); txResponse.txFee = txResponse.gasPriceEther * txResponse.gasUsed; - if (config.settings.useFiat) { - const latestPrice = await Market.findOne().sort({timestamp: -1}) - txResponse.txFeeUSD = txResponse.txFee * latestPrice.quoteUSD; - txResponse.valueUSD = txResponse.value * latestPrice.quoteUSD; - } + const latestPrice = await Market.findOne().sort({timestamp: -1}) + txResponse.txFeeUSD = txResponse.txFee * latestPrice.quoteUSD; + txResponse.valueUSD = txResponse.value * latestPrice.quoteUSD; res.write(JSON.stringify(txResponse)); res.end(); @@ -203,10 +201,8 @@ exports.data = async (req, res) => { } } - if (config.settings.useFiat) { - const latestPrice = await Market.findOne().sort({timestamp: -1}) - addrData["balanceUSD"] = addrData.balance * latestPrice.quoteUSD; - } + const latestPrice = await Market.findOne().sort({timestamp: -1}) + addrData["balanceUSD"] = addrData.balance * latestPrice.quoteUSD; res.write(JSON.stringify(addrData)); res.end(); From 0765a4809591e56cf804593daf98a81b21fdcd61 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 09:00:51 +0900 Subject: [PATCH 29/46] cleanup: apply eslint --- .eslintignore | 3 + .eslintrc.js | 164 +++++++++ app.js | 60 ++-- db.js | 304 ++++++++-------- lib/etherUnits.js | 95 ++--- package-lock.json | 820 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 9 +- routes/compiler.js | 110 +++--- routes/contracts.js | 41 +-- routes/filters.js | 112 +++--- routes/index.js | 225 ++++++------ routes/richlist.js | 61 ++-- routes/stats.js | 244 +++++++------ routes/token.js | 66 ++-- routes/web3relay.js | 297 ++++++++-------- tools/richlist.js | 259 +++++++------- tools/stats.js | 254 +++++++------- tools/sync.js | 559 +++++++++++++++--------------- 18 files changed, 2343 insertions(+), 1340 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..a6d1da957 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +db-internal.js +gulpfile.js +*.min.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..c3a515b80 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,164 @@ +module.exports = { + "env": { + "browser": true, + "es6": true + }, + "extends": "airbnb-base", + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "rules": { + "array-bracket-spacing": 2, + "block-scoped-var": 2, + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "comma-spacing": [2, { "before": false, "after": true }], + "comma-style": [2, "last"], + "complexity": 0, + "consistent-return": 1, + "consistent-this": 0, + "curly": [2, "multi-line"], + "default-case": 0, + "dot-location": [2, "property"], + "dot-notation": 0, + "eol-last": 2, + "eqeqeq": [2, "allow-null"], + "func-names": 0, + "func-style": 0, + "generator-star-spacing": [2, "both"], + "guard-for-in": 0, + "handle-callback-err": [2, "^(err|error|anySpecificError)$" ], + "indent": [2, 2, { "SwitchCase": 1 }], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "linebreak-style": 0, + "max-depth": 0, + "max-len": [2, 1550, 4], + "max-nested-callbacks": 0, + "max-params": 0, + "max-statements": 0, + "new-cap": [2, { "newIsCap": true, "capIsNew": false }], + "newline-after-var": [0, "never"], + "new-parens": 2, + "no-alert": 0, + "no-array-constructor": 2, + "no-bitwise": 0, + "no-caller": 2, + "no-catch-shadow": 0, + "no-cond-assign": 2, + "no-console": 0, + "no-constant-condition": 0, + "no-continue": 0, + "no-control-regex": 2, + "no-debugger": 0, + "no-delete-var": 2, + "no-div-regex": 0, + "no-dupe-args": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-else-return": 2, + "no-empty": 0, + "no-empty-character-class": 2, + "no-labels": 2, + "no-eq-null": 0, + "no-eval": 2, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-extra-boolean-cast": 2, + "no-extra-parens": 0, + "no-extra-semi": 0, + "no-extra-strict": 0, + "no-fallthrough": 2, + "no-floating-decimal": 2, + "no-func-assign": 2, + "no-implied-eval": 2, + "no-inline-comments": 0, + "no-inner-declarations": [2, "functions"], + "no-invalid-regexp": 2, + "no-irregular-whitespace": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-lone-blocks": 0, + "no-lonely-if": 0, + "no-loop-func": 0, + "no-mixed-requires": 0, + "no-mixed-spaces-and-tabs": [2, false], + "no-multi-spaces": 2, + "no-multi-str": 0, + "no-multiple-empty-lines": [2, { "max": 1 }], + "no-native-reassign": 2, + "no-negated-in-lhs": 2, + "no-nested-ternary": 0, + "no-new": 2, + "no-new-func": 2, + "no-new-object": 2, + "no-new-require": 2, + "no-new-wrappers": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 2, + "no-path-concat": 0, + "no-plusplus": 0, + "no-process-env": 0, + "no-process-exit": 0, + "no-proto": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-reserved-keys": 0, + "no-restricted-modules": 0, + "no-script-url": 0, + "no-self-compare": 2, + "no-sequences": 2, + "no-shadow": 0, + "no-shadow-restricted-names": 2, + "no-spaced-func": 2, + "no-sparse-arrays": 2, + "no-sync": 0, + "no-ternary": 0, + "no-throw-literal": 2, + "no-trailing-spaces": 2, + "no-undef": 0, + "no-undef-init": 2, + "no-undefined": 0, + "no-underscore-dangle": 0, + "no-unneeded-ternary": 2, + "no-unreachable": 2, + "no-unused-expressions": 0, + "no-unused-vars": [2, { "vars": "all", "args": "none" }], + "no-var": 2, + "no-void": 0, + "no-warning-comments": 0, + "no-with": 2, + "object-curly-spacing": [2, "always"], + "one-var": 0, + "operator-assignment": 0, + "operator-linebreak": [2, "after"], + "padded-blocks": 0, + "prefer-const": 2, + "quote-props": 0, + "quotes": [2, "single", "avoid-escape"], + "radix": 2, + "jsx-quotes": [2, "prefer-single"], + "semi-spacing": 0, + "sort-vars": 0, + "space-before-blocks": [2, "always"], + "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], + "space-in-parens": [2, "never"], + "space-infix-ops": 2, + "keyword-spacing": 2, + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-comment": [0, "always"], + "strict": 0, + "use-isnan": 2, + "valid-jsdoc": 0, + "valid-typeof": 2, + "vars-on-top": 2, + "wrap-iife": [2, "any"], + "wrap-regex": 0, + "yoda": [2, "never"] + } +}; diff --git a/app.js b/app.js index d2b941a3a..a0ffb12b7 100644 --- a/app.js +++ b/app.js @@ -1,17 +1,17 @@ #!/usr/bin/env node -require( './db' ); +require('./db'); -var express = require('express'); -var path = require('path'); -var favicon = require('serve-favicon'); -var logger = require('morgan'); -var bodyParser = require('body-parser'); +const express = require('express'); +const path = require('path'); +const favicon = require('serve-favicon'); +const logger = require('morgan'); +const bodyParser = require('body-parser'); -var config = {}; +let config = {}; try { config = require('./config.json'); -} catch(e) { +} catch (e) { if (e.code == 'MODULE_NOT_FOUND') { console.log('No config file found. Using default configuration... (config.example.json)'); config = require('./config.example.json'); @@ -21,37 +21,36 @@ try { } } -var app = express(); +const app = express(); app.set('port', process.env.PORT || 3000); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); -app.use(favicon(__dirname + '/public/favicon.ico')); +app.use(favicon(`${__dirname}/public/favicon.ico`)); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(__dirname, 'public'))); // app libraries -global.__lib = __dirname + '/lib/'; - +global.__lib = `${__dirname}/lib/`; // client -app.get('/', function(req, res) { +app.get('/', (req, res) => { res.render('index', config); }); -app.get('/config', function(req, res) { +app.get('/config', (req, res) => { res.json(config.settings); }); require('./routes')(app); // let angular catch them -app.use(function(req, res) { +app.use((req, res) => { res.render('index', config); }); @@ -60,28 +59,27 @@ app.use(function(req, res) { // development error handler // will print stacktrace if (app.get('env') === 'development') { - app.use(function(err, req, res, next) { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: err - }); + app.use((err, req, res, next) => { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err, }); + }); } - // production error handler // no stacktraces leaked to user -app.use(function(err, req, res, next) { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: {} - }); +app.use((err, req, res, next) => { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {}, + }); }); -var http = require('http').Server(app); +const http = require('http').Server(app); -http.listen(app.get('port'), '0.0.0.0', function() { - console.log('Express server listening on port ' + app.get('port')); +http.listen(app.get('port'), '0.0.0.0', () => { + console.log(`Express server listening on port ${app.get('port')}`); }); diff --git a/db.js b/db.js index 9c21715ef..46885bb1b 100644 --- a/db.js +++ b/db.js @@ -1,148 +1,156 @@ -var mongoose = require( 'mongoose' ); -var Schema = mongoose.Schema; - -var Block = new Schema( -{ - "number": {type: Number, index: {unique: true}}, - "hash": String, - "parentHash": String, - "nonce": String, - "sha3Uncles": String, - "logsBloom": String, - "transactionsRoot": String, - "stateRoot": String, - "receiptRoot": String, - "miner": {type: String, lowercase: true}, - "difficulty": String, - "totalDifficulty": String, - "size": Number, - "extraData": String, - "gasLimit": Number, - "gasUsed": Number, - "timestamp": Number, - "blockTime": Number, - "uncles": [String] -}, {collection: "Block"}); - -var Account = new Schema( -{ - "address": {type: String, index: {unique: true}}, - "balance": Number, - "blockNumber": Number, - "type": {type: Number, default: 0} // address: 0x0, contract: 0x1 -}, {collection: "Account"}); - -var Contract = new Schema( -{ - "address": {type: String, index: {unique: true}}, - "blockNumber": Number, - "ERC": {type: Number, index: true}, //0:normal contract, 2:ERC20, 3:ERC223 - "creationTransaction": String, - "contractName": String, - "tokenName": String, - "symbol": String, - "owner": String, - "decimals": Number, - "totalSupply": Number, - "compilerVersion": String, - "optimization": Boolean, - "sourceCode": String, - "abi": String, - "byteCode": String -}, {collection: "Contract"}); - -var Transaction = new Schema( -{ - "hash": {type: String, index: {unique: true}, lowercase: true}, - "nonce": Number, - "blockHash": String, - "blockNumber": Number, - "transactionIndex": Number, - "status": Number, - "from": {type: String, lowercase: true}, - "to": {type: String, lowercase: true}, - "creates": {type: String, lowercase: true}, - "value": String, - "gas": Number, - "gasUsed": Number, - "gasPrice": String, - "timestamp": Number, - "input": String -}, {collection: "Transaction"}); - -var TokenTransfer = new Schema( -{ - "hash": {type: String, index: {unique: true}, lowercase: true}, - "blockNumber": Number, - "method": String, - "from": {type: String, lowercase: true}, - "to": {type: String, lowercase: true}, - "contract": {type: String, lowercase: true}, - "value": String, - "timestamp": Number -}, {collection: "TokenTransfer"}); - -var BlockStat = new Schema( -{ - "number": {type: Number, index: {unique: true}}, - "timestamp": Number, - "difficulty": String, - "hashrate": String, - "txCount": Number, - "gasUsed": Number, - "gasLimit": Number, - "miner": String, - "blockTime": Number, - "uncleCount": Number -}, {collection: "BlockStat"}); - -var Market = new Schema( -{ - "symbol": String, - "timestamp": Number, - "quoteBTC": Number, - "quoteUSD": Number -}, {collection: "Market"}); - -// create indices -Transaction.index({blockNumber:-1}); -Transaction.index({from:1, blockNumber:-1}); -Transaction.index({to:1, blockNumber:-1}); -Transaction.index({creates:1, blockNumber:-1}); -Account.index({balance:-1}); -Account.index({balance:-1, blockNumber:-1}); -Account.index({type:-1, balance:-1}); -Block.index({miner:1}); -Block.index({miner:1, blockNumber:-1}); -Block.index({hash:1, number:-1}); -Market.index({timestamp: -1}); -TokenTransfer.index({blockNumber:-1}); -TokenTransfer.index({from:1, blockNumber:-1}); -TokenTransfer.index({to:1, blockNumber:-1}); -TokenTransfer.index({contract:1, blockNumber:-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); -mongoose.model('TokenTransfer', TokenTransfer); -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'); -module.exports.TokenTransfer = mongoose.model('TokenTransfer'); - -mongoose.Promise = global.Promise; -mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/explorerDB', { - useMongoClient: true - // poolSize: 5, - // rs_name: 'myReplicaSetName', - // user: 'explorer', - // pass: 'yourdbpasscode' -}); - -// mongoose.set('debug', true); +const mongoose = require('mongoose'); + +const { Schema } = mongoose; + +const Block = new Schema( + { + 'number': { type: Number, index: { unique: true } }, + 'hash': String, + 'parentHash': String, + 'nonce': String, + 'sha3Uncles': String, + 'logsBloom': String, + 'transactionsRoot': String, + 'stateRoot': String, + 'receiptRoot': String, + 'miner': { type: String, lowercase: true }, + 'difficulty': String, + 'totalDifficulty': String, + 'size': Number, + 'extraData': String, + 'gasLimit': Number, + 'gasUsed': Number, + 'timestamp': Number, + 'blockTime': Number, + 'uncles': [String], + }, { collection: 'Block' }, +); + +const Account = new Schema( + { + 'address': { type: String, index: { unique: true } }, + 'balance': Number, + 'blockNumber': Number, + 'type': { type: Number, default: 0 }, // address: 0x0, contract: 0x1 + }, { collection: 'Account' }, +); + +const Contract = new Schema( + { + 'address': { type: String, index: { unique: true } }, + 'blockNumber': Number, + 'ERC': { type: Number, index: true }, //0:normal contract, 2:ERC20, 3:ERC223 + 'creationTransaction': String, + 'contractName': String, + 'tokenName': String, + 'symbol': String, + 'owner': String, + 'decimals': Number, + 'totalSupply': Number, + 'compilerVersion': String, + 'optimization': Boolean, + 'sourceCode': String, + 'abi': String, + 'byteCode': String, + }, { collection: 'Contract' }, +); + +const Transaction = new Schema( + { + 'hash': { type: String, index: { unique: true }, lowercase: true }, + 'nonce': Number, + 'blockHash': String, + 'blockNumber': Number, + 'transactionIndex': Number, + 'status': Number, + 'from': { type: String, lowercase: true }, + 'to': { type: String, lowercase: true }, + 'creates': { type: String, lowercase: true }, + 'value': String, + 'gas': Number, + 'gasUsed': Number, + 'gasPrice': String, + 'timestamp': Number, + 'input': String, + }, { collection: 'Transaction' }, +); + +const TokenTransfer = new Schema( + { + 'hash': { type: String, index: { unique: true }, lowercase: true }, + 'blockNumber': Number, + 'method': String, + 'from': { type: String, lowercase: true }, + 'to': { type: String, lowercase: true }, + 'contract': { type: String, lowercase: true }, + 'value': String, + 'timestamp': Number, + }, { collection: 'TokenTransfer' }, +); + +const BlockStat = new Schema( + { + 'number': { type: Number, index: { unique: true } }, + 'timestamp': Number, + 'difficulty': String, + 'hashrate': String, + 'txCount': Number, + 'gasUsed': Number, + 'gasLimit': Number, + 'miner': String, + 'blockTime': Number, + 'uncleCount': Number, + }, { collection: 'BlockStat' }, +); + +const Market = new Schema( + { + 'symbol': String, + 'timestamp': Number, + 'quoteBTC': Number, + 'quoteUSD': Number, + }, { collection: 'Market' }, +); + +// create indices +Transaction.index({ blockNumber: -1 }); +Transaction.index({ from: 1, blockNumber: -1 }); +Transaction.index({ to: 1, blockNumber: -1 }); +Transaction.index({ creates: 1, blockNumber: -1 }); +Account.index({ balance: -1 }); +Account.index({ balance: -1, blockNumber: -1 }); +Account.index({ type: -1, balance: -1 }); +Block.index({ miner: 1 }); +Block.index({ miner: 1, blockNumber: -1 }); +Block.index({ hash: 1, number: -1 }); +Market.index({ timestamp: -1 }); +TokenTransfer.index({ blockNumber: -1 }); +TokenTransfer.index({ from: 1, blockNumber: -1 }); +TokenTransfer.index({ to: 1, blockNumber: -1 }); +TokenTransfer.index({ contract: 1, blockNumber: -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); +mongoose.model('TokenTransfer', TokenTransfer); +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'); +module.exports.TokenTransfer = mongoose.model('TokenTransfer'); + +mongoose.Promise = global.Promise; +mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/explorerDB', { + useMongoClient: true + // poolSize: 5, + // rs_name: 'myReplicaSetName', + // user: 'explorer', + // pass: 'yourdbpasscode' +}); + +// mongoose.set('debug', true); diff --git a/lib/etherUnits.js b/lib/etherUnits.js index e69d6fe37..519641f27 100644 --- a/lib/etherUnits.js +++ b/lib/etherUnits.js @@ -1,55 +1,56 @@ -'use strict'; -var BigNumber = require('bignumber.js'); +'use strict'; -var etherUnits = function() {} +const BigNumber = require('bignumber.js'); + +const etherUnits = function () {}; etherUnits.unitMap = { - 'wei': '1', - 'kwei': '1000', - 'ada': '1000', - 'femtoether': '1000', - 'mwei': '1000000', - 'babbage': '1000000', - 'picoether': '1000000', - 'gwei': '1000000000', - 'shannon': '1000000000', - 'nanoether': '1000000000', - 'nano': '1000000000', - 'szabo': '1000000000000', - 'microether': '1000000000000', - 'micro': '1000000000000', - 'finney': '1000000000000000', - 'milliether': '1000000000000000', - 'milli': '1000000000000000', - 'ether': '1000000000000000000', - 'kether': '1000000000000000000000', - 'grand': '1000000000000000000000', - 'einstein': '1000000000000000000000', - 'mether': '1000000000000000000000000', - 'gether': '1000000000000000000000000000', - 'tether': '1000000000000000000000000000000' + 'wei': '1', + 'kwei': '1000', + 'ada': '1000', + 'femtoether': '1000', + 'mwei': '1000000', + 'babbage': '1000000', + 'picoether': '1000000', + 'gwei': '1000000000', + 'shannon': '1000000000', + 'nanoether': '1000000000', + 'nano': '1000000000', + 'szabo': '1000000000000', + 'microether': '1000000000000', + 'micro': '1000000000000', + 'finney': '1000000000000000', + 'milliether': '1000000000000000', + 'milli': '1000000000000000', + 'ether': '1000000000000000000', + 'kether': '1000000000000000000000', + 'grand': '1000000000000000000000', + 'einstein': '1000000000000000000000', + 'mether': '1000000000000000000000000', + 'gether': '1000000000000000000000000000', + 'tether': '1000000000000000000000000000000', +}; +etherUnits.getValueOfUnit = function (unit) { + unit = unit ? unit.toLowerCase() : 'ether'; + const unitValue = this.unitMap[unit]; + if (unitValue === undefined) { + throw new Error(globalFuncs.errorMsgs[4] + JSON.stringify(this.unitMap, null, 2)); + } + return new BigNumber(unitValue, 10); }; -etherUnits.getValueOfUnit = function(unit) { - unit = unit ? unit.toLowerCase() : 'ether'; - var unitValue = this.unitMap[unit]; - if (unitValue === undefined) { - throw new Error(globalFuncs.errorMsgs[4] + JSON.stringify(this.unitMap, null, 2)); - } - return new BigNumber(unitValue, 10); -} -etherUnits.toEther = function(number, unit) { - var returnValue = new BigNumber(this.toWei(number, unit)).div(this.getValueOfUnit('ether')); - return returnValue.toString(10); -} +etherUnits.toEther = function (number, unit) { + const returnValue = new BigNumber(this.toWei(number, unit)).div(this.getValueOfUnit('ether')); + return returnValue.toString(10); +}; -etherUnits.toGwei = function(number, unit) { - var returnValue = new BigNumber(this.toWei(number, unit)).div(this.getValueOfUnit('gwei')); - return returnValue.toString(10); -} +etherUnits.toGwei = function (number, unit) { + const returnValue = new BigNumber(this.toWei(number, unit)).div(this.getValueOfUnit('gwei')); + return returnValue.toString(10); +}; -etherUnits.toWei = function(number, unit) { - var returnValue = new BigNumber(String(number)).times(this.getValueOfUnit(unit)); - return returnValue.toString(10); -} +etherUnits.toWei = function (number, unit) { + const returnValue = new BigNumber(String(number)).times(this.getValueOfUnit(unit)); + return returnValue.toString(10); +}; module.exports = etherUnits; diff --git a/package-lock.json b/package-lock.json index 1a0910681..bb4c2475e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,26 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, "@types/node": { "version": "10.14.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.1.tgz", @@ -18,6 +38,18 @@ "negotiator": "0.6.1" } }, + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true + }, "aes-js": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", @@ -40,6 +72,12 @@ "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", "dev": true }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -131,6 +169,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", @@ -522,6 +566,12 @@ "unset-value": "^1.0.0" } }, + "callsites": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", + "dev": true + }, "camelcase": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", @@ -566,6 +616,12 @@ } } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -604,6 +660,21 @@ } } }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", @@ -690,6 +761,12 @@ "yargs": "^12.0.1" } }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -940,6 +1017,12 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -1035,6 +1118,15 @@ "randombytes": "^2.0.0" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-walk": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", @@ -1078,6 +1170,12 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -1137,12 +1235,203 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "eslint": { + "version": "5.15.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.15.3.tgz", + "integrity": "sha512-vMGi0PjCHSokZxE0NLp2VneGw5sio7SSiDNgIUn2tC0XkWJRNOIoHIg3CliLVfXnJsiHxGAYrkw0PieAu8+KYQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.12.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "eslint-config-airbnb-base": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz", + "integrity": "sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==", + "dev": true, + "requires": { + "eslint-restricted-globals": "^0.1.1", + "object.assign": "^4.1.0", + "object.entries": "^1.0.4" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", + "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", + "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", + "dev": true, + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.3.0", + "has": "^1.0.3", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "read-pkg-up": "^2.0.0", + "resolve": "^1.9.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-restricted-globals": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -1390,6 +1679,28 @@ } } }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -1470,6 +1781,12 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -1478,6 +1795,24 @@ "pend": "~1.2.0" } }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "file-type": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", @@ -1569,6 +1904,23 @@ } } }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -1677,6 +2029,12 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -1756,6 +2114,12 @@ "which": "^1.2.14" } }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, "got": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", @@ -1984,6 +2348,36 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2004,6 +2398,44 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "inquirer": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", + "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.11", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -2174,6 +2606,12 @@ "isobject": "^3.0.1" } }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -2246,6 +2684,12 @@ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.6.1.tgz", "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA=" }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "js-yaml": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", @@ -2276,6 +2720,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -2347,6 +2797,45 @@ "invert-kv": "^2.0.0" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -2742,6 +3231,12 @@ "resolved": "https://registry.npmjs.org/muri/-/muri-1.3.0.tgz", "integrity": "sha512-FiaFwKl864onHFFUV/a2szAl7X0fxVlSKNdhTf+BM8i8goEgYut8u5P9MqQqIYwvaMxjzVESsoEm/2kfkFH1rg==" }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -2781,6 +3276,12 @@ "to-regex": "^3.0.1" } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -2912,6 +3413,18 @@ "object-keys": "^1.0.11" } }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -2960,6 +3473,37 @@ "wrappy": "1" } }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, "os-locale": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", @@ -3024,6 +3568,15 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==" }, + "parent-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.0.tgz", + "integrity": "sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-asn1": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", @@ -3082,6 +3635,12 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -3097,6 +3656,23 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", @@ -3143,12 +3719,72 @@ "pinkie": "^2.0.0" } }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + } + } + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", @@ -3164,6 +3800,12 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "proxy-addr": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", @@ -3273,6 +3915,72 @@ "pify": "^3.0.0" } }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + } + } + }, "readable-stream": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", @@ -3302,6 +4010,12 @@ "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -3394,6 +4108,16 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -3426,6 +4150,15 @@ "safe-buffer": "^5.1.1" } }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, "rxjs": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", @@ -3665,6 +4398,17 @@ "simple-concat": "^1.0.0" } }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, "sliced": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", @@ -4089,6 +4833,12 @@ "ansi-regex": "^3.0.0" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", @@ -4162,6 +4912,46 @@ } } }, + "table": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", + "dev": true, + "requires": { + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "tar": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", @@ -4234,6 +5024,12 @@ } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "thenify": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", @@ -4354,6 +5150,15 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -4876,6 +5681,12 @@ "string-width": "^1.0.2 || 2" } }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", @@ -4923,6 +5734,15 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", diff --git a/package.json b/package.json index 00212f897..8e68d0902 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,10 @@ "app": "node app.js", "sync": "node tools/sync.js", "stats": "node tools/stats.js", - "rich": "node tools/richlist.js", - "test": "mocha --exit" + "rich": "node tools/richlist.js", + "test": "mocha --exit", + "lint:check": "eslint *.js ./lib/*.js ./routes/*.js ./tools/*.js", + "lint:fix": "eslint *.js ./lib/*.js ./routes/*.js ./tools/*.js --fix" }, "dependencies": { "bignumber.js": "^8.1.1", @@ -29,6 +31,9 @@ }, "devDependencies": { "chai": "^4.2.0", + "eslint": "^5.15.3", + "eslint-config-airbnb-base": "^13.1.0", + "eslint-plugin-import": "^2.16.0", "mocha": "^6.0.2", "request": "^2.88.0" } diff --git a/routes/compiler.js b/routes/compiler.js index 113ad42a2..3111148c8 100644 --- a/routes/compiler.js +++ b/routes/compiler.js @@ -1,62 +1,58 @@ -var solc = require('solc'); -var eth = require('./web3relay').eth; -var Contract = require('./contracts'); +const solc = require('solc'); +const { eth } = require('./web3relay'); +const Contract = require('./contracts'); /* TODO: support other languages */ -module.exports = function(req, res) { +module.exports = function (req, res) { console.log(req.body); - if (!("action" in req.body)) - res.status(400).send(); - if (req.body.action=="compile") { + if (!('action' in req.body)) res.status(400).send(); + if (req.body.action == 'compile') { compileSolc(req, res); - } else if (req.body.action=="find") { + } else if (req.body.action == 'find') { Contract.findContract(req.body.addr, res); } -} - +}; var compileSolc = async (req, res) => { // get bytecode at address - var address = req.body.address; - var version = req.body.version; - var name = req.body.name; - var input = req.body.code; - var optimization = (req.body.optimization) ? true : false; - var optimise = (optimization) ? 1 : 0; - - var bytecode = await eth.getCode(address); - if (bytecode.substring(0,2)=="0x") - bytecode = bytecode.substring(2); - - var data = { - "address": address, - "compilerVersion": version, - "optimization": optimization, - "contractName": name, - "sourceCode": input - } - - console.log(version) + const { address } = req.body; + const { version } = req.body; + const { name } = req.body; + const input = req.body.code; + const optimization = !!(req.body.optimization); + const optimise = (optimization) ? 1 : 0; + + let bytecode = await eth.getCode(address); + if (bytecode.substring(0, 2) == '0x') bytecode = bytecode.substring(2); + + const data = { + 'address': address, + 'compilerVersion': version, + 'optimization': optimization, + 'contractName': name, + 'sourceCode': input, + }; + + console.log(version); try { // latest version doesn't need to be loaded remotely - if (version == "latest") { - var output = solc.compile(input, optimise); - testValidCode(output, data, bytecode, res); + if (version == 'latest') { + const output = solc.compile(input, optimise); + testValidCode(output, data, bytecode, res); } else { - solc.loadRemoteVersion(version, function(err, solcV) { + solc.loadRemoteVersion(version, (err, solcV) => { if (err) { console.error(err); - res.write(JSON.stringify({"valid": false})); + res.write(JSON.stringify({ 'valid': false })); res.end(); - } - else { - var output = solcV.compile(input, optimise); + } else { + const output = solcV.compile(input, optimise); testValidCode(output, data, bytecode, res); } }); @@ -66,30 +62,31 @@ var compileSolc = async (req, res) => { console.error(e.stack); } -} +}; -var testValidCode = function(output, data, bytecode, response) { - var verifiedContracts = []; +var testValidCode = function (output, data, bytecode, response) { + const verifiedContracts = []; for (var contractName in output.contracts) { // code and ABI that are needed by web3 - console.log(contractName + ': ' + output.contracts[contractName].bytecode); - verifiedContracts.push({"name": contractName, - "abi": output.contracts[contractName].interface, - "bytecode": output.contracts[contractName].bytecode}); + console.log(`${contractName}: ${output.contracts[contractName].bytecode}`); + verifiedContracts.push({ + 'name': contractName, + 'abi': output.contracts[contractName].interface, + 'bytecode': output.contracts[contractName].bytecode, + }); } // Remove swarm hash - var bytecodeClean = bytecode.replace(/a165627a7a72305820.{64}0029$/gi, ""); + const bytecodeClean = bytecode.replace(/a165627a7a72305820.{64}0029$/gi, ''); - var contractName = ':' + data.contractName; // XXX + var contractName = `:${data.contractName}`; // XXX // compare to bytecode at address - if (!output.contracts || !output.contracts[contractName]) - data.valid = false; - else if (output.contracts[contractName].bytecode.indexOf(bytecodeClean) > -1){ - var contractBytecodeClean = output.contracts[contractName].bytecode.replace(/a165627a7a72305820.{64}0029$/gi, ""); - constructorArgs = contractBytecodeClean.replace(bytecodeClean, ""); - contractBytecodeClean = contractBytecodeClean.replace(constructorArgs, ""); + if (!output.contracts || !output.contracts[contractName]) data.valid = false; + else if (output.contracts[contractName].bytecode.indexOf(bytecodeClean) > -1) { + let contractBytecodeClean = output.contracts[contractName].bytecode.replace(/a165627a7a72305820.{64}0029$/gi, ''); + constructorArgs = contractBytecodeClean.replace(bytecodeClean, ''); + contractBytecodeClean = contractBytecodeClean.replace(constructorArgs, ''); if (contractBytecodeClean == bytecodeClean) { data.valid = true; @@ -100,10 +97,9 @@ var testValidCode = function(output, data, bytecode, response) { } else { data.valid = false; } - } else - data.valid = false; + } else data.valid = false; - data["verifiedContracts"] = verifiedContracts; + data['verifiedContracts'] = verifiedContracts; response.write(JSON.stringify(data)); response.end(); -} +}; diff --git a/routes/contracts.js b/routes/contracts.js index d03ccca5a..ec6bf5e66 100644 --- a/routes/contracts.js +++ b/routes/contracts.js @@ -2,35 +2,36 @@ Stuff to deal with verified contracts in DB */ -require( '../db.js' ); -var mongoose = require( 'mongoose' ); -var Contract = mongoose.model( 'Contract' ); +require('../db.js'); +const mongoose = require('mongoose'); -exports.addContract = function(contract) { +const Contract = mongoose.model('Contract'); + +exports.addContract = function (contract) { Contract.update( - {address: contract.address}, - {$setOnInsert: contract}, - {upsert: true}, - function (err, data) { + { address: contract.address }, + { $setOnInsert: contract }, + { upsert: true }, + (err, data) => { console.log(data); - } + }, ); -} +}; -exports.findContract = function(address, res) { - var contractFind = Contract.findOne({ address : address}).lean(true); - contractFind.exec(function(err, doc) { +exports.findContract = function (address, res) { + const contractFind = Contract.findOne({ address }).lean(true); + contractFind.exec((err, doc) => { if (err) { - console.error("ContractFind error: " + err); - console.error("bad address: " + address); - res.write(JSON.stringify({"error": true, "valid": false})); + console.error(`ContractFind error: ${err}`); + console.error(`bad address: ${address}`); + res.write(JSON.stringify({ 'error': true, 'valid': false })); } else if (!doc || !doc.sourceCode) { - res.write(JSON.stringify({"valid": false})); + res.write(JSON.stringify({ 'valid': false })); } else { - var data = doc; + const data = doc; data.valid = true; res.write(JSON.stringify(data)); } res.end(); - }) -} + }); +}; diff --git a/routes/filters.js b/routes/filters.js index a20e65c26..dadc7f49b 100644 --- a/routes/filters.js +++ b/routes/filters.js @@ -1,127 +1,111 @@ 'use strict'; -var etherUnits = require(__lib + "etherUnits.js") -var BigNumber = require('bignumber.js'); -var RLP = require('rlp'); + +const etherUnits = require(`${__lib}etherUnits.js`); +const BigNumber = require('bignumber.js'); +const RLP = require('rlp'); /* Filter an array of TX */ function filterTX(txs, value) { - return txs.map(function(tx){ - return [tx.hash, tx.blockNumber, tx.from, tx.to, etherUnits.toEther(new BigNumber(tx.value), 'ether'), tx.gas, tx.timestamp, tx.creates] - }) + return txs.map(tx => [tx.hash, tx.blockNumber, tx.from, tx.to, etherUnits.toEther(new BigNumber(tx.value), 'ether'), tx.gas, tx.timestamp, tx.creates]); } function filterTrace(txs, value) { - return txs.map(function(tx){ - var t = tx; - if (t.type == "suicide") { - if (t.action.address) - t.from = t.action.address; - if (t.action.balance) - t.value = etherUnits.toEther( new BigNumber(t.action.balance), "wei"); - if (t.action.refundAddress) - t.to = t.action.refundAddress; + return txs.map((tx) => { + const t = tx; + if (t.type == 'suicide') { + if (t.action.address) t.from = t.action.address; + if (t.action.balance) t.value = etherUnits.toEther(new BigNumber(t.action.balance), 'wei'); + if (t.action.refundAddress) t.to = t.action.refundAddress; } else { - if (t.action.to) - t.to = t.action.to; + if (t.action.to) t.to = t.action.to; t.from = t.action.from; - if (t.action.gas) - t.gas = new BigNumber(t.action.gas).toNumber(); - if ((t.result) && (t.result.gasUsed)) - t.gasUsed = new BigNumber(t.result.gasUsed).toNumber(); - if ((t.result) && (t.result.address)) - t.to = t.result.address; - t.value = etherUnits.toEther( new BigNumber(t.action.value), "wei"); + if (t.action.gas) t.gas = new BigNumber(t.action.gas).toNumber(); + if ((t.result) && (t.result.gasUsed)) t.gasUsed = new BigNumber(t.result.gasUsed).toNumber(); + if ((t.result) && (t.result.address)) t.to = t.result.address; + t.value = etherUnits.toEther(new BigNumber(t.action.value), 'wei'); } return t; - }) + }); } function filterBlock(block, field, value) { - var tx = block.transactions.filter(function(obj) { - return obj[field]==value; - }); + let tx = block.transactions.filter(obj => obj[field] == value); tx = tx[0]; - if (typeof tx !== "undefined") - tx.timestamp = block.timestamp; + if (typeof tx !== 'undefined') tx.timestamp = block.timestamp; return tx; } /* make blocks human readable */ function filterBlocks(blocks) { if (blocks.constructor !== Array) { - var b = blocks; - var ascii = hex2ascii(blocks.extraData); + const b = blocks; + const ascii = hex2ascii(blocks.extraData); b.extraDataHex = blocks.extraData; b.extraData = ascii; return b; } - return blocks.map(function(block) { - var b = block; - var ascii = hex2ascii(block.extraData); + return blocks.map((block) => { + const b = block; + const ascii = hex2ascii(block.extraData); b.extraDataHex = block.extraData; b.extraData = ascii; return b; - }) + }); } /* stupid datatable format */ function datatableTX(txs) { - return txs.map(function(tx){ - return [tx.hash, tx.blockNumber, tx.from, tx.to, - etherUnits.toEther(new BigNumber(tx.value), 'wei'), tx.gas, tx.timestamp] - }) + return txs.map(tx => [tx.hash, tx.blockNumber, tx.from, tx.to, + etherUnits.toEther(new BigNumber(tx.value), 'wei'), tx.gas, tx.timestamp]); } function internalTX(txs) { - return txs.map(function(tx){ - return [tx.transactionHash, tx.blockNumber, tx.action.from, tx.action.to, - etherUnits.toEther(new BigNumber(tx.action.value), 'wei'), tx.action.gas, tx.timestamp] - }) + return txs.map(tx => [tx.transactionHash, tx.blockNumber, tx.action.from, tx.action.to, + etherUnits.toEther(new BigNumber(tx.action.value), 'wei'), tx.action.gas, tx.timestamp]); } /* modified baToJSON() routine from rlp */ function baToString(ba) { if (Buffer.isBuffer(ba)) { return ba.toString('ascii'); - } else if (ba instanceof Array) { - var array = []; - for (var i = 0; i < ba.length; i++) { + } if (ba instanceof Array) { + const array = []; + for (let i = 0; i < ba.length; i++) { array.push(baToString(ba[i])); } return array.join('/'); - } else { - return ba; } + return ba; + } var hex2ascii = function (hexIn) { - var hex = hexIn.toString(); - var str = ''; + const hex = hexIn.toString(); + let str = ''; try { - var ba = RLP.decode(hex); - var test = ba[1].toString('ascii'); + const ba = RLP.decode(hex); + const test = ba[1].toString('ascii'); if (test == 'geth' || test == 'Parity') { // FIXME ba[0] = ba[0].toString('hex'); } str = baToString(ba); - } catch(e) { - for (var i = 0; i < hex.length; i += 2) - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + } catch (e) { + for (let i = 0; i < hex.length; i += 2) str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); } return str; -} +}; module.exports = { - filterBlock: filterBlock, - filterBlocks: filterBlocks, - filterTX: filterTX, - filterTrace: filterTrace, - datatableTX: datatableTX, - internalTX: internalTX -} + filterBlock, + filterBlocks, + filterTX, + filterTrace, + datatableTX, + internalTX, +}; diff --git a/routes/index.js b/routes/index.js index 9f43e576c..31f13c6e2 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,20 +1,19 @@ -var mongoose = require( 'mongoose' ); +const mongoose = require('mongoose'); -var Block = mongoose.model( 'Block' ); -var Transaction = mongoose.model( 'Transaction' ); -var Account = mongoose.model('Account'); -var filters = require('./filters'); +const Block = mongoose.model('Block'); +const Transaction = mongoose.model('Transaction'); +const Account = mongoose.model('Account'); +const async = require('async'); +const filters = require('./filters'); -var async = require('async'); +module.exports = function (app) { + const web3relay = require('./web3relay'); -module.exports = function(app){ - var web3relay = require('./web3relay'); + const Token = require('./token'); - var Token = require('./token'); - - var compile = require('./compiler'); - var stats = require('./stats'); - var richList = require('./richlist'); + const compile = require('./compiler'); + const stats = require('./stats'); + const richList = require('./richlist'); /* Local DB: data request format @@ -35,21 +34,23 @@ module.exports = function(app){ app.post('/compile', compile); app.post('/stats', stats); -} +}; const getAddr = async (req, res) => { // TODO: validate addr and tx - var addr = req.body.addr.toLowerCase(); - var count = parseInt(req.body.count); + const addr = req.body.addr.toLowerCase(); + const count = parseInt(req.body.count); - var limit = parseInt(req.body.length); - var start = parseInt(req.body.start); + const limit = parseInt(req.body.length); + const start = parseInt(req.body.start); - var data = { draw: parseInt(req.body.draw), recordsFiltered: count, recordsTotal: count, mined: 0 }; + const data = { + draw: parseInt(req.body.draw), recordsFiltered: count, recordsTotal: count, mined: 0, + }; - var addrFind = Transaction.find( { $or: [{"to": addr}, {"from": addr}] }) + const addrFind = Transaction.find({ $or: [{ 'to': addr }, { 'from': addr }] }); - var sortOrder = '-blockNumber'; + let sortOrder = '-blockNumber'; if (req.body.order && req.body.order[0] && req.body.order[0].column) { // date or blockNumber column if (req.body.order[0].column == 1 || req.body.order[0].column == 6) { @@ -59,78 +60,77 @@ const getAddr = async (req, res) => { } } - addrFind.lean(true).sort(sortOrder).skip(start).limit(limit).exec("find", function (err, docs) { - if (docs) - data.data = filters.filterTX(docs, addr); - else - data.data = []; + addrFind.lean(true).sort(sortOrder).skip(start).limit(limit) + .exec('find', (err, docs) => { + if (docs) data.data = filters.filterTX(docs, addr); + else data.data = []; res.write(JSON.stringify(data)); res.end(); - }); + }); }; -var getAddrCounter = function(req, res) { - var addr = req.body.addr.toLowerCase(); - var count = parseInt(req.body.count); - var data = { recordsFiltered: count, recordsTotal: count, mined: 0 }; +var getAddrCounter = function (req, res) { + const addr = req.body.addr.toLowerCase(); + const count = parseInt(req.body.count); + const data = { recordsFiltered: count, recordsTotal: count, mined: 0 }; async.waterfall([ - function(callback) { + function (callback) { - Transaction.count({ $or: [{"to": addr}, {"from": addr}] }, function(err, count) { - if (!err && count) { - // fix recordsTotal - data.recordsTotal = count; - data.recordsFiltered = count; - } - callback(null); - }); + Transaction.count({ $or: [{ 'to': addr }, { 'from': addr }] }, (err, count) => { + if (!err && count) { + // fix recordsTotal + data.recordsTotal = count; + data.recordsFiltered = count; + } + callback(null); + }); - }, function(callback) { + }, function (callback) { - Block.count({ "miner": addr }, function(err, count) { - if (!err && count) { - data.mined = count; - } - callback(null); - }); + Block.count({ 'miner': addr }, (err, count) => { + if (!err && count) { + data.mined = count; + } + callback(null); + }); - }], function (err) { + }], (err) => { res.write(JSON.stringify(data)); res.end(); }); }; -var getBlock = function(req, res) { +var getBlock = function (req, res) { // TODO: support queries for block hash - var txQuery = "number"; - var number = parseInt(req.body.block); + const txQuery = 'number'; + const number = parseInt(req.body.block); - var blockFind = Block.findOne( { number : number }).lean(true); - blockFind.exec(function (err, doc) { + const blockFind = Block.findOne({ number }).lean(true); + blockFind.exec((err, doc) => { if (err || !doc) { - console.error("BlockFind error: " + err) + console.error(`BlockFind error: ${err}`); console.error(req.body); - res.write(JSON.stringify({"error": true})); + res.write(JSON.stringify({ 'error': true })); } else { - var block = filters.filterBlocks([doc]); + const block = filters.filterBlocks([doc]); res.write(JSON.stringify(block[0])); } res.end(); }); }; -var getTx = function(req, res){ - var tx = req.body.tx.toLowerCase(); - var txFind = Block.findOne( { "transactions.hash" : tx }, "transactions timestamp") - .lean(true); - txFind.exec(function (err, doc) { - if (!doc){ - console.log("missing: " +tx) +var getTx = function (req, res) { + const tx = req.body.tx.toLowerCase(); + const txFind = Block.findOne({ 'transactions.hash': tx }, 'transactions timestamp') + .lean(true); + txFind.exec((err, doc) => { + if (!doc) { + console.log(`missing: ${tx}`); res.write(JSON.stringify({})); res.end(); } else { // filter transactions - var txDocs = filters.filterBlock(doc, "hash", tx) + const txDocs = filters.filterBlock(doc, 'hash', tx); res.write(JSON.stringify(txDocs)); res.end(); } @@ -139,19 +139,17 @@ var getTx = function(req, res){ /* Fetch data from DB */ -var getData = function(req, res){ +var getData = function (req, res) { // TODO: error handling for invalid calls - var action = req.body.action.toLowerCase(); - var limit = req.body.limit + const action = req.body.action.toLowerCase(); + const { limit } = req.body; if (action in DATA_ACTIONS) { - if (isNaN(limit)) - var lim = MAX_ENTRIES; - else - var lim = parseInt(limit); + if (isNaN(limit)) var lim = MAX_ENTRIES; + else var lim = parseInt(limit); DATA_ACTIONS[action](lim, res); } else { - console.error("Invalid Request: " + action) + console.error(`Invalid Request: ${action}`); res.status(400).send(); } }; @@ -159,84 +157,83 @@ var getData = function(req, res){ /* Total supply API code */ -var getTotal = function(req, res) { +var getTotal = function (req, res) { Account.aggregate([ - { $group: { _id: null, totalSupply: { $sum: '$balance' } } } - ]).exec(function(err, docs) { + { $group: { _id: null, totalSupply: { $sum: '$balance' } } }, + ]).exec((err, docs) => { if (err) { - res.write("Error getting total supply"); - res.end() + res.write('Error getting total supply'); + res.end(); } res.write(docs[0].totalSupply.toString()); res.end(); }); -} +}; /* temporary blockstats here */ -var latestBlock = function(req, res) { - var block = Block.findOne({}, "totalDifficulty") - .lean(true).sort('-number'); - block.exec(function (err, doc) { +const latestBlock = function (req, res) { + const block = Block.findOne({}, 'totalDifficulty') + .lean(true).sort('-number'); + block.exec((err, doc) => { res.write(JSON.stringify(doc)); res.end(); }); -} - +}; -var getLatest = function(lim, res, callback) { - var blockFind = Block.find({}, "number transactions timestamp miner extraData") - .lean(true).sort('-number').limit(lim); - blockFind.exec(function (err, docs) { +const getLatest = function (lim, res, callback) { + const blockFind = Block.find({}, 'number transactions timestamp miner extraData') + .lean(true).sort('-number').limit(lim); + blockFind.exec((err, docs) => { callback(docs, res); }); -} +}; /* get blocks from db */ -var sendBlocks = function(lim, res) { - var blockFind = Block.find({}, "number timestamp miner extraData") - .lean(true).sort('-number').limit(lim); - blockFind.exec(function (err, docs) { - if(!err && docs) { - var blockNumber = docs[docs.length - 1].number; +const sendBlocks = function (lim, res) { + const blockFind = Block.find({}, 'number timestamp miner extraData') + .lean(true).sort('-number').limit(lim); + blockFind.exec((err, docs) => { + if (!err && docs) { + const blockNumber = docs[docs.length - 1].number; // aggregate transaction counters Transaction.aggregate([ - {$match: { blockNumber: { $gte: blockNumber } }}, - {$group: { _id: '$blockNumber', count: { $sum: 1 } }} - ]).exec(function(err, results) { - var txns = {}; + { $match: { blockNumber: { $gte: blockNumber } } }, + { $group: { _id: '$blockNumber', count: { $sum: 1 } } }, + ]).exec((err, results) => { + const txns = {}; if (!err && results) { // set transaction counters - results.forEach(function(txn) { + results.forEach((txn) => { txns[txn._id] = txn.count; }); - docs.forEach(function(doc) { + docs.forEach((doc) => { doc.txn = txns[doc.number] || 0; }); } - res.write(JSON.stringify({"blocks": filters.filterBlocks(docs)})); + res.write(JSON.stringify({ 'blocks': filters.filterBlocks(docs) })); res.end(); }); } else { - console.log("blockFind error:" + err); - res.write(JSON.stringify({"error": true})); + console.log(`blockFind error:${err}`); + res.write(JSON.stringify({ 'error': true })); res.end(); } }); -} +}; -var sendTxs = function(lim, res) { +const sendTxs = function (lim, res) { Transaction.find({}).lean(true).sort('-blockNumber').limit(lim) - .exec(function (err, txs) { - res.write(JSON.stringify({"txs": txs})); - res.end(); - }); -} + .exec((err, txs) => { + res.write(JSON.stringify({ 'txs': txs })); + res.end(); + }); +}; const MAX_ENTRIES = 10; const DATA_ACTIONS = { - "latest_blocks": sendBlocks, - "latest_txs": sendTxs -} + 'latest_blocks': sendBlocks, + 'latest_txs': sendTxs, +}; diff --git a/routes/richlist.js b/routes/richlist.js index 8516645c2..6772f1757 100644 --- a/routes/richlist.js +++ b/routes/richlist.js @@ -3,47 +3,48 @@ * Endpoint for richlist */ -var async = require('async'); -var mongoose = require('mongoose'); +const async = require('async'); +const mongoose = require('mongoose'); -require( '../db.js' ); -var Account = mongoose.model('Account'); +require('../db.js'); -var getAccounts = function(req, res) { - var self = getAccounts; +const Account = mongoose.model('Account'); + +var getAccounts = function (req, res) { + const self = getAccounts; if (!self.totalSupply) { self.totalSupply = -1; self.timestamp = 0; } // check cached totalSupply - if (new Date() - self.timestamp > 30*60*1000) { + if (new Date() - self.timestamp > 30 * 60 * 1000) { self.totalSupply = -1; self.timestamp = 0; } // count accounts only once - var count = req.body.recordsTotal || 0; + let count = req.body.recordsTotal || 0; count = parseInt(count); if (count < 0) { count = 0; } // get totalSupply only once - var queryTotalSupply = self.totalSupply || req.body.totalSupply || null; + const queryTotalSupply = self.totalSupply || req.body.totalSupply || null; async.waterfall([ - function(callback) { + function (callback) { if (queryTotalSupply < 0) { Account.aggregate([ - { $group: { _id: null, totalSupply: { $sum: '$balance' } } } - ]).exec(function(err, docs) { + { $group: { _id: null, totalSupply: { $sum: '$balance' } } }, + ]).exec((err, docs) => { if (err) { callbck(err); return; } - var totalSupply = docs[0].totalSupply; + const { totalSupply } = docs[0]; // update cache self.timestamp = new Date(); self.totalSupply = totalSupply; @@ -53,10 +54,10 @@ var getAccounts = function(req, res) { callback(null, queryTotalSupply > 0 ? queryTotalSupply : null); } }, - function(totalSupply, callback) { + function (totalSupply, callback) { if (!count) { // get the number of all accounts - Account.count({}, function(err, count) { + Account.count({}, (err, count) => { if (err) { callbck(err); return; @@ -68,16 +69,16 @@ var getAccounts = function(req, res) { } else { callback(null, totalSupply, count); } - } - ], function(error, totalSupply, count) { + }, + ], (error, totalSupply, count) => { if (error) { - res.write(JSON.stringify({"error": true})); + res.write(JSON.stringify({ 'error': true })); res.end(); return; } // check sort order - var sortOrder = { balance: -1 }; + let sortOrder = { balance: -1 }; if (req.body.order && req.body.order[0] && req.body.order[0].column) { // balance column if (req.body.order[0].column == 3) { @@ -94,30 +95,28 @@ var getAccounts = function(req, res) { } // set datatable params - var limit = parseInt(req.body.length); - var start = parseInt(req.body.start); + const limit = parseInt(req.body.length); + const start = parseInt(req.body.start); - var data = { draw: parseInt(req.body.draw), recordsFiltered: count, recordsTotal: count }; + const data = { draw: parseInt(req.body.draw), recordsFiltered: count, recordsTotal: count }; if (totalSupply > 0) { data.totalSupply = totalSupply; } - Account.find({}).lean(true).sort(sortOrder).skip(start).limit(limit) - .exec(function (err, accounts) { + Account.find({}).lean(true).sort(sortOrder).skip(start) + .limit(limit) + .exec((err, accounts) => { if (err) { - res.write(JSON.stringify({"error": true})); + res.write(JSON.stringify({ 'error': true })); res.end(); return; } - data.data = accounts.map(function(account, i) { - return [i + 1 + start, account.address, account.type, account.balance, account.blockNumber]; - }); + data.data = accounts.map((account, i) => [i + 1 + start, account.address, account.type, account.balance, account.blockNumber]); res.write(JSON.stringify(data)); res.end(); - } - ); + }); }); -} +}; module.exports = getAccounts; diff --git a/routes/stats.js b/routes/stats.js index 68943f409..243ba5a8e 100644 --- a/routes/stats.js +++ b/routes/stats.js @@ -1,17 +1,18 @@ -var mongoose = require( 'mongoose' ); -var Block = mongoose.model( 'Block' ); -var BlockStat = mongoose.model( 'BlockStat' ); -var filters = require('./filters'); +const mongoose = require('mongoose'); -var https = require('https'); -var async = require('async'); +const Block = mongoose.model('Block'); +const BlockStat = mongoose.model('BlockStat'); -var etherUnits = require(__lib + "etherUnits.js") +const https = require('https'); +const async = require('async'); +const filters = require('./filters'); -var config = {}; +const etherUnits = require(`${__lib}etherUnits.js`); + +let config = {}; try { config = require('../config.json'); -} catch(e) { +} catch (e) { if (e.code == 'MODULE_NOT_FOUND') { console.log('No config file found. Using default configuration... (config.example.json)'); config = require('../config.example.json'); @@ -21,26 +22,18 @@ try { } } -module.exports = function(req, res) { +module.exports = function (req, res) { - if (!("action" in req.body)) - res.status(400).send(); - - else if (req.body.action=="miners") - getMinerStats(req, res) - - else if (req.body.action=="hashrate") - getHashrate(res); + if (!('action' in req.body)) res.status(400).send(); - else if (req.body.action=="hashrates") - getHashrates(req, res); - -} + else if (req.body.action == 'miners') { getMinerStats(req, res); } else if (req.body.action == 'hashrate') { getHashrate(res); } else if (req.body.action == 'hashrates') getHashrates(req, res); + +}; /** Aggregate miner stats **/ -var getMinerStats = function(req, res) { - var range = 6*60*60; // 6 hours +var getMinerStats = function (req, res) { + let range = 6 * 60 * 60; // 6 hours // check validity of range if (req.body.range && req.body.range < 60 * 60 * 24 * 7) { range = parseInt(req.body.range); @@ -49,31 +42,34 @@ var getMinerStats = function(req, res) { } } - var timebefore = parseInt((new Date())/1000) - range; - Block.find({ timestamp: { $lte: timebefore } }, "timestamp number") - .lean(true).sort('-number').limit(1).exec(function (err, docs) { - if (err || !docs) { - console.error(err); - res.status(500).send(); - res.end(); - return; - } - var blockNumber = docs[0].number; - console.log('getMinerStats(): blockNumber = ' + blockNumber); - Block.aggregate([ + const timebefore = parseInt((new Date()) / 1000) - range; + Block.find({ timestamp: { $lte: timebefore } }, 'timestamp number') + .lean(true).sort('-number').limit(1) + .exec((err, docs) => { + if (err || !docs) { + console.error(err); + res.status(500).send(); + res.end(); + return; + } + const blockNumber = docs[0].number; + console.log(`getMinerStats(): blockNumber = ${blockNumber}`); + Block.aggregate([ { $match: { number: { $gte: blockNumber } } }, - { $group: { - _id: '$miner', - timestamp: {$min: '$timestamp' }, - count: {$sum: 1} } - } - ], function (err, result) { + { + $group: { + _id: '$miner', + timestamp: { $min: '$timestamp' }, + count: { $sum: 1 }, + }, + }, + ], (err, result) => { if (err) { console.error(err); res.status(500).send(); } else { if (config.settings.miners) { - result.forEach(function(m) { + result.forEach((m) => { if (config.settings.miners[m._id]) { m._id = config.settings.miners[m._id]; } @@ -82,22 +78,22 @@ var getMinerStats = function(req, res) { res.write(JSON.stringify(result)); res.end(); } + }); }); - }); -} +}; /** Aggregate network hashrates **/ -var getHashrates = function(req, res) { +var getHashrates = function (req, res) { // setup default range //var range = 7 * 24 * 60 * 60; /* 7 days */ //var range = 14 * 24 * 60 * 60; /* 14 days */ //var range = 30 * 24 * 60 * 60; /* 1 months */ //var range = 2 * 30 * 24 * 60 * 60; /* 2 months */ - var range = 6 * 30 * 24 * 60 * 60; /* 6 months */ + let range = 6 * 30 * 24 * 60 * 60; /* 6 months */ if (req.body.days && req.body.days <= 365) { - var days = parseInt(req.body.days); + let days = parseInt(req.body.days); if (days <= 1) { days = 1; } @@ -110,131 +106,133 @@ var getHashrates = function(req, res) { } // select mod - var rngs = [ 30*60, 60*60, 2*60*60, 4*60*60, 6*60*60, - 12*60*60, 24*60*60, 7*24*60*60, 14*24*60*60, 30*24*60*60 - ]; - var mods = [ 1, 1, 2, 10, 10, - 15, 30, 15*60, 30*60, 30*60, - 60*60 - ]; - var i = 0; - rngs.forEach(function(r) { + const rngs = [30 * 60, 60 * 60, 2 * 60 * 60, 4 * 60 * 60, 6 * 60 * 60, + 12 * 60 * 60, 24 * 60 * 60, 7 * 24 * 60 * 60, 14 * 24 * 60 * 60, 30 * 24 * 60 * 60, + ]; + const mods = [1, 1, 2, 10, 10, + 15, 30, 15 * 60, 30 * 60, 30 * 60, + 60 * 60, + ]; + let i = 0; + rngs.forEach((r) => { if (range > r) { i++; } - return; + }); - var mod = mods[i]; + const mod = mods[i]; - var timestamp = parseInt((new Date())/1000) - range; + const timestamp = parseInt((new Date()) / 1000) - range; BlockStat.aggregate([ { $match: { timestamp: { $gte: timestamp } } }, - { $group: { - _id: { + { + $group: { + _id: { timestamp: { - $subtract: [ '$timestamp', { $mod: [ '$timestamp', mod ] } ] - } + $subtract: ['$timestamp', { $mod: ['$timestamp', mod] }], + }, + }, + blockTime: { $avg: '$blockTime' }, + difficulty: { $max: '$difficulty' }, + count: { $sum: 1 }, }, - blockTime: { $avg: '$blockTime' }, - difficulty: { $max: '$difficulty' }, - count: { $sum: 1 } - }}, - { $project: { - "_id": 0, - "timestamp": '$_id.timestamp', - "blockTime": 1, - "difficulty": 1, - "count": 1, - } - }]).sort('timestamp').exec(function(err, docs) { - var hashrates = []; - docs.forEach(function(doc) { + }, + { + $project: { + '_id': 0, + 'timestamp': '$_id.timestamp', + 'blockTime': 1, + 'difficulty': 1, + 'count': 1, + }, + }]).sort('timestamp').exec((err, docs) => { + const hashrates = []; + docs.forEach((doc) => { doc.instantHashrate = doc.difficulty / doc.blockTime; doc.unixtime = doc.timestamp; /* FIXME */ doc.timestamp = doc.timestamp; }); - res.write(JSON.stringify({"hashrates": docs})); + res.write(JSON.stringify({ 'hashrates': docs })); res.end(); }); -} +}; /** Get hashrate Diff stuff **/ -var getHashrate = function(res) { - var blockFind = Block.find({}, "difficulty timestamp number") - .lean(true).sort('-number').limit(100); - blockFind.exec(function (err, docs) { - var blockTime = (docs[0].timestamp - docs[99].timestamp)/100; - var hashrate = docs[0].difficulty / blockTime; +var getHashrate = function (res) { + const blockFind = Block.find({}, 'difficulty timestamp number') + .lean(true).sort('-number').limit(100); + blockFind.exec((err, docs) => { + const blockTime = (docs[0].timestamp - docs[99].timestamp) / 100; + const hashrate = docs[0].difficulty / blockTime; res.write(JSON.stringify({ - "blocks": docs, - "hashrate": hashrate, - "blockTime": blockTime, - "blockHeight": docs[0].number, - "difficulty": docs[0].difficulty + 'blocks': docs, + 'hashrate': hashrate, + 'blockTime': blockTime, + 'blockHeight': docs[0].number, + 'difficulty': docs[0].difficulty, })); res.end(); }); -} +}; /** OLD CODE DON'T USE Swipe ETC ETH data **/ -var getEtcEth = function(res) { - var options = [{ +const getEtcEth = function (res) { + const options = [{ host: 'api.minergate.com', path: '/1.0/etc/status', method: 'GET', - data: 'etc' - },{ + data: 'etc', + }, { host: 'api.minergate.com', path: '/1.0/eth/status', method: 'GET', - data: 'eth' + data: 'eth', }]; - - async.map(options, function(opt, callback) { - - https.request(opt, function(mg) { - mg.on('data', function (data) { + + async.map(options, (opt, callback) => { + + https.request(opt, (mg) => { + mg.on('data', (data) => { try { - var result = JSON.parse(data.toString()); + const result = JSON.parse(data.toString()); result.chain = opt.data; callback(null, result); } catch (e) { callback(e); } - }) + }); }).end(); - }, function(err, results) { + }, (err, results) => { if (err) { console.error(err); res.status(500).send(); } else { - if (results.length < 2) - res.status(500).send(); + if (results.length < 2) res.status(500).send(); else { - var c = ((results[0].chain == "etc") ? 0 : 1); - var h = 1 - c; - var etcHashrate = parseInt(results[c].instantHashrate); - var ethHashrate = parseInt(results[h].instantHashrate); - var etcDiff = results[c].difficulty.toFixed(2); - var ethDiff = results[h].difficulty.toFixed(2); - var etcEthHash = parseInt(100*etcHashrate/ethHashrate); - var etcEthDiff = parseInt(100*etcDiff/ethDiff); + const c = ((results[0].chain == 'etc') ? 0 : 1); + const h = 1 - c; + const etcHashrate = parseInt(results[c].instantHashrate); + const ethHashrate = parseInt(results[h].instantHashrate); + const etcDiff = results[c].difficulty.toFixed(2); + const ethDiff = results[h].difficulty.toFixed(2); + const etcEthHash = parseInt(100 * etcHashrate / ethHashrate); + const etcEthDiff = parseInt(100 * etcDiff / ethDiff); res.write(JSON.stringify({ - "etcHashrate": etcHashrate, - "ethHashrate": ethHashrate, - "etcDiff": etcDiff, - "ethDiff": ethDiff, - "etcEthHash": etcEthHash, - "etcEthDiff": etcEthDiff + 'etcHashrate': etcHashrate, + 'ethHashrate': ethHashrate, + 'etcDiff': etcDiff, + 'ethDiff': ethDiff, + 'etcEthHash': etcEthHash, + 'etcEthDiff': etcEthDiff, })); res.end(); - } + } } }); -} +}; diff --git a/routes/token.js b/routes/token.js index 6173b066b..8db7f42d9 100644 --- a/routes/token.js +++ b/routes/token.js @@ -4,49 +4,59 @@ Endpoint for client interface with ERC-20 tokens */ -var eth = require('./web3relay').eth; +const { eth } = require('./web3relay'); -var BigNumber = require('bignumber.js'); -var etherUnits = require(__lib + "etherUnits.js") +const BigNumber = require('bignumber.js'); -const ABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"}]; +const etherUnits = require(`${__lib}etherUnits.js`); + +const ABI = [{ + 'constant': true, 'inputs': [], 'name': 'name', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'type': 'function', +}, { + 'constant': true, 'inputs': [], 'name': 'totalSupply', 'outputs': [{ 'name': '', 'type': 'uint256' }], 'payable': false, 'type': 'function', +}, { + 'constant': true, 'inputs': [], 'name': 'decimals', 'outputs': [{ 'name': '', 'type': 'uint8' }], 'payable': false, 'type': 'function', +}, { + 'constant': true, 'inputs': [{ 'name': '', 'type': 'address' }], 'name': 'balanceOf', 'outputs': [{ 'name': '', 'type': 'uint256' }], 'payable': false, 'type': 'function', +}, { + 'constant': true, 'inputs': [], 'name': 'symbol', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'type': 'function', +}]; module.exports = async (req, res) => { - console.log(req.body) + console.log(req.body); - var contractAddress = req.body.address; + const contractAddress = req.body.address; - var Token = new eth.Contract(ABI, contractAddress); + const Token = new eth.Contract(ABI, contractAddress); - if (!("action" in req.body)) - res.status(400).send(); - else if (req.body.action=="info") { + if (!('action' in req.body)) res.status(400).send(); + else if (req.body.action == 'info') { try { - var actualBalance = await eth.getBalance(contractAddress); + let actualBalance = await eth.getBalance(contractAddress); actualBalance = etherUnits.toEther(actualBalance, 'wei'); - var totalSupply = await Token.methods.totalSupply().call(); - var name = await Token.methods.name().call(); - var symbol = await Token.methods.symbol().call(); - var count = await eth.getTransactionCount(contractAddress); - - var tokenData = { - "balance": actualBalance, - "total_supply": totalSupply, - "count": count, - "name": name, - "symbol": symbol, - "bytecode": await eth.getCode(contractAddress) - } + const totalSupply = await Token.methods.totalSupply().call(); + const name = await Token.methods.name().call(); + const symbol = await Token.methods.symbol().call(); + const count = await eth.getTransactionCount(contractAddress); + + const tokenData = { + 'balance': actualBalance, + 'total_supply': totalSupply, + 'count': count, + 'name': name, + 'symbol': symbol, + 'bytecode': await eth.getCode(contractAddress), + }; res.write(JSON.stringify(tokenData)); res.end(); } catch (e) { console.error(e); } - } else if (req.body.action=="balanceOf") { - var addr = req.body.user.toLowerCase(); + } else if (req.body.action == 'balanceOf') { + const addr = req.body.user.toLowerCase(); try { - var tokens = await Token.methods.balanceOf(addr).call(); - res.write(JSON.stringify({"tokens": tokens})); + const tokens = await Token.methods.balanceOf(addr).call(); + res.write(JSON.stringify({ 'tokens': tokens })); res.end(); } catch (e) { console.error(e); diff --git a/routes/web3relay.js b/routes/web3relay.js index 47cfc6ef6..aa117a3ef 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -4,99 +4,100 @@ Endpoint for client to talk to etc node */ -var Web3 = require("web3"); -var web3explorer = require('web3-explorer'); -var web3; +const Web3 = require('web3'); +const web3explorer = require('web3-explorer'); -var _ = require('lodash'); -var BigNumber = require('bignumber.js'); -var etherUnits = require(__lib + "etherUnits.js") +let web3; -require( '../db.js' ); -const mongoose = require( 'mongoose' ); -const Block = mongoose.model( 'Block' ); -const Transaction = mongoose.model( 'Transaction' ); -const Market = mongoose.model( 'Market' ); +const _ = require('lodash'); +const BigNumber = require('bignumber.js'); -var getLatestBlocks = require('./index').getLatestBlocks; -var filterBlocks = require('./filters').filterBlocks; -var filterTrace = require('./filters').filterTrace; +const etherUnits = require(`${__lib}etherUnits.js`); + +require('../db.js'); +const mongoose = require('mongoose'); + +const Block = mongoose.model('Block'); +const Transaction = mongoose.model('Transaction'); +const Market = mongoose.model('Market'); + +const { getLatestBlocks } = require('./index'); +const { filterBlocks } = require('./filters'); +const { filterTrace } = require('./filters'); /*Start config for node connection and sync*/ // load config.json -var config = { nodeAddr: 'localhost', wsPort: 8546 }; +const config = { nodeAddr: 'localhost', wsPort: 8546 }; try { - var local = require('../config.json'); - _.extend(config, local); - console.log('config.json found.'); + 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); - } + 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); + } } //Create Web3 connection -console.log('Connecting ' + config.nodeAddr + ':' + config.wsPort + '...'); -web3 = new Web3(new Web3.providers.WebsocketProvider('ws://' + config.nodeAddr +':'+ config.wsPort)); +console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); +web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort}`)); -if (web3.eth.net.isListening()) - console.log("Web3 connection established"); -else - throw "No connection, please specify web3host in conf.json"; +if (web3.eth.net.isListening()) console.log('Web3 connection established'); +else throw 'No connection, please specify web3host in conf.json'; async function detectNode() { - var nodeInfo = await web3.eth.getNodeInfo(); + const nodeInfo = await web3.eth.getNodeInfo(); if (nodeInfo.split('/')[0].toLowerCase().includes('parity')) { - console.log("Web3 has detected parity node configuration"); + console.log('Web3 has detected parity node configuration'); web3explorer(web3); } - console.log("Node version = " + nodeInfo); + console.log(`Node version = ${nodeInfo}`); } detectNode(); exports.data = async (req, res) => { - console.log(req.body) + console.log(req.body); - if ("tx" in req.body) { + if ('tx' in req.body) { var txHash = req.body.tx.toLowerCase(); - Transaction.findOne({hash: txHash}).lean(true).exec(async(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) { - console.error("TxWeb3 error :" + err) + web3.eth.getTransaction(txHash, (err, tx) => { + if (err || !tx) { + console.error(`TxWeb3 error :${err}`); if (!tx) { - web3.eth.getBlock(txHash, function(err, block) { - if(err || !block) { - console.error("BlockWeb3 error :" + err) - res.write(JSON.stringify({"error": true})); + web3.eth.getBlock(txHash, (err, block) => { + if (err || !block) { + console.error(`BlockWeb3 error :${err}`); + res.write(JSON.stringify({ 'error': true })); } else { - console.log("BlockWeb3 found: " + txHash) - res.write(JSON.stringify({"error": true, "isBlock": true})); + console.log(`BlockWeb3 found: ${txHash}`); + res.write(JSON.stringify({ 'error': true, 'isBlock': true })); } res.end(); }); } else { - res.write(JSON.stringify({"error": true})); + res.write(JSON.stringify({ 'error': true })); res.end(); } } else { - var ttx = tx; - ttx.value = etherUnits.toEther( new BigNumber(tx.value), "wei"); + const ttx = tx; + ttx.value = etherUnits.toEther(new BigNumber(tx.value), 'wei'); //get TxReceipt status & gasUsed - web3.eth.getTransactionReceipt(txHash, function(err, receipt) { + web3.eth.getTransactionReceipt(txHash, (err, receipt) => { if (err) { console.error(err); return; } ttx.gasUsed = receipt.gasUsed; - if(receipt.status) { + if (receipt.status) { ttx.status = receipt.status; } if (!tx.to && !tx.creates) { @@ -106,10 +107,9 @@ exports.data = async (req, res) => { } }); //get timestamp from block - var block = web3.eth.getBlock(tx.blockNumber, function(err, block) { - if (!err && block) - ttx.timestamp = block.timestamp; - ttx.isTrace = (ttx.input != "0x"); + const block = web3.eth.getBlock(tx.blockNumber, (err, block) => { + if (!err && block) ttx.timestamp = block.timestamp; + ttx.isTrace = (ttx.input != '0x'); txResponse = ttx; }); } @@ -125,11 +125,11 @@ exports.data = async (req, res) => { if (txResponse.confirmations === latestBlock) { txResponse.confirmation = 0; } - txResponse.gasPriceGwei = etherUnits.toGwei( new BigNumber(txResponse.gasPrice), "wei"); - txResponse.gasPriceEther = etherUnits.toEther( new BigNumber(txResponse.gasPrice), "wei"); + txResponse.gasPriceGwei = etherUnits.toGwei(new BigNumber(txResponse.gasPrice), 'wei'); + txResponse.gasPriceEther = etherUnits.toEther(new BigNumber(txResponse.gasPrice), 'wei'); txResponse.txFee = txResponse.gasPriceEther * txResponse.gasUsed; - const latestPrice = await Market.findOne().sort({timestamp: -1}) + const latestPrice = await Market.findOne().sort({ timestamp: -1 }); txResponse.txFeeUSD = txResponse.txFee * latestPrice.quoteUSD; txResponse.valueUSD = txResponse.value * latestPrice.quoteUSD; @@ -137,171 +137,172 @@ exports.data = async (req, res) => { res.end(); }); - } else if ("tx_trace" in req.body) { + } else if ('tx_trace' in req.body) { var txHash = req.body.tx_trace.toLowerCase(); - web3.trace.transaction(txHash, function(err, tx) { - if(err || !tx) { - console.error("TraceWeb3 error :" + err) - res.write(JSON.stringify({"error": true})); + web3.trace.transaction(txHash, (err, tx) => { + if (err || !tx) { + console.error(`TraceWeb3 error :${err}`); + res.write(JSON.stringify({ 'error': true })); } else { res.write(JSON.stringify(filterTrace(tx))); } res.end(); }); - } else if ("addr_trace" in req.body) { + } else if ('addr_trace' in req.body) { var addr = req.body.addr_trace.toLowerCase(); // need to filter both to and from // from block to end block, paging "toAddress":[addr], // start from creation block to speed things up // TODO: store creation block - var filter = {"fromBlock":"0x1d4c00", "toAddress":[addr]}; - web3.trace.filter(filter, function(err, tx) { - if(err || !tx) { - console.error("TraceWeb3 error :" + err) - res.write(JSON.stringify({"error": true})); + const filter = { 'fromBlock': '0x1d4c00', 'toAddress': [addr] }; + web3.trace.filter(filter, (err, tx) => { + if (err || !tx) { + console.error(`TraceWeb3 error :${err}`); + res.write(JSON.stringify({ 'error': true })); } else { res.write(JSON.stringify(filterTrace(tx))); } res.end(); - }) - } else if ("addr" in req.body) { + }); + } else if ('addr' in req.body) { var addr = req.body.addr.toLowerCase(); - var options = req.body.options; + const { options } = req.body; - var addrData = {}; + let addrData = {}; - if (options.indexOf("balance") > -1) { + if (options.indexOf('balance') > -1) { try { - addrData["balance"] = await web3.eth.getBalance(addr); - addrData["balance"] = etherUnits.toEther(addrData["balance"], 'wei'); - } catch(err) { - console.error("AddrWeb3 error :" + err); - addrData = {"error": true}; + addrData['balance'] = await web3.eth.getBalance(addr); + addrData['balance'] = etherUnits.toEther(addrData['balance'], 'wei'); + } catch (err) { + console.error(`AddrWeb3 error :${err}`); + addrData = { 'error': true }; } } - if (options.indexOf("count") > -1) { + if (options.indexOf('count') > -1) { try { - addrData["count"] = await web3.eth.getTransactionCount(addr); + addrData['count'] = await web3.eth.getTransactionCount(addr); } catch (err) { - console.error("AddrWeb3 error :" + err); - addrData = {"error": true}; + console.error(`AddrWeb3 error :${err}`); + addrData = { 'error': true }; } } - if (options.indexOf("bytecode") > -1) { + if (options.indexOf('bytecode') > -1) { try { - addrData["bytecode"] = await web3.eth.getCode(addr); - if (addrData["bytecode"].length > 2) - addrData["isContract"] = true; - else - addrData["isContract"] = false; + addrData['bytecode'] = await web3.eth.getCode(addr); + if (addrData['bytecode'].length > 2) addrData['isContract'] = true; + else addrData['isContract'] = false; } catch (err) { - console.error("AddrWeb3 error :" + err); - addrData = {"error": true}; + console.error(`AddrWeb3 error :${err}`); + addrData = { 'error': true }; } } - const latestPrice = await Market.findOne().sort({timestamp: -1}) - addrData["balanceUSD"] = addrData.balance * latestPrice.quoteUSD; + 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) { + } else if ('block' in req.body) { var blockNumOrHash; if (/^(0x)?[0-9a-f]{64}$/i.test(req.body.block.trim())) { - blockNumOrHash = req.body.block.toLowerCase(); + blockNumOrHash = req.body.block.toLowerCase(); } else { - blockNumOrHash = parseInt(req.body.block); + blockNumOrHash = parseInt(req.body.block); } - Block.findOne({$or: [{hash: blockNumOrHash}, {number: blockNumOrHash}]}, - { '_id': 0 }).lean(true).exec("findOne", function(err, doc) { - if (err || !doc) { - web3.eth.getBlock(blockNumOrHash, function(err, block) { - if(err || !block) { - console.error("BlockWeb3 error :" + err) - res.write(JSON.stringify({"error": true})); - } else { - res.write(JSON.stringify(filterBlocks(block))); - } - res.end(); - }); - } else { - Transaction.find({blockNumber: doc.number}).distinct("hash", (err, txs) => { - doc["transactions"] = txs; - res.write(JSON.stringify(filterBlocks(doc))); - res.end(); - }); - } + Block.findOne({ $or: [{ hash: blockNumOrHash }, { number: blockNumOrHash }] }, + { '_id': 0 }).lean(true).exec('findOne', (err, doc) => { + if (err || !doc) { + web3.eth.getBlock(blockNumOrHash, (err, block) => { + if (err || !block) { + console.error(`BlockWeb3 error :${err}`); + res.write(JSON.stringify({ 'error': true })); + } else { + res.write(JSON.stringify(filterBlocks(block))); + } + res.end(); + }); + } else { + Transaction.find({ blockNumber: doc.number }).distinct('hash', (err, txs) => { + doc['transactions'] = txs; + res.write(JSON.stringify(filterBlocks(doc))); + res.end(); + }); + } }); /* / TODO: Refactor, "block" / "uncle" determinations should likely come later / Can parse out the request once and then determine the path. */ - } else if ("uncle" in req.body) { - var uncle = req.body.uncle.trim(); - var arr = uncle.split('/'); + } else if ('uncle' in req.body) { + const uncle = req.body.uncle.trim(); + const arr = uncle.split('/'); var blockNumOrHash; // Ugly, does the same as blockNumOrHash above - var uncleIdx = parseInt(arr[1]) || 0; + const uncleIdx = parseInt(arr[1]) || 0; if (/^(?:0x)?[0-9a-f]{64}$/i.test(arr[0])) { blockNumOrHash = arr[0].toLowerCase(); - console.log(blockNumOrHash) + console.log(blockNumOrHash); } else { blockNumOrHash = parseInt(arr[0]); } - if (typeof blockNumOrHash == 'undefined') { - console.error("UncleWeb3 error :" + err); - res.write(JSON.stringify({"error": true})); + if (typeof blockNumOrHash === 'undefined') { + console.error(`UncleWeb3 error :${err}`); + res.write(JSON.stringify({ 'error': true })); res.end(); return; } - web3.eth.getBlock(blockNumOrHash, uncleIdx, function(err, uncle) { - if(err || !uncle) { - console.error("UncleWeb3 error :" + err) - res.write(JSON.stringify({"error": true})); + web3.eth.getBlock(blockNumOrHash, uncleIdx, (err, uncle) => { + if (err || !uncle) { + console.error(`UncleWeb3 error :${err}`); + res.write(JSON.stringify({ 'error': true })); } else { res.write(JSON.stringify(filterBlocks(uncle))); } res.end(); }); - } else if ("action" in req.body) { + } else if ('action' in req.body) { if (req.body.action == 'hashrate') { - web3.eth.getBlock('latest', function(err, latest) { - if(err || !latest) { - console.error("StatsWeb3 error :" + err); - res.write(JSON.stringify({"error": true})); + web3.eth.getBlock('latest', (err, latest) => { + if (err || !latest) { + console.error(`StatsWeb3 error :${err}`); + res.write(JSON.stringify({ 'error': true })); res.end(); } else { - console.log("StatsWeb3: latest block: " + latest.number); - var checknum = latest.number - 100; - if(checknum < 0) - checknum = 0; - var nblock = latest.number - checknum; - web3.eth.getBlock(checknum, function(err, block) { - if(err || !block) { - console.error("StatsWeb3 error :" + err); - res.write(JSON.stringify({"blockHeight": latest.number, "difficulty": latest.difficulty, "blockTime": 0, "hashrate": 0 })); + console.log(`StatsWeb3: latest block: ${latest.number}`); + let checknum = latest.number - 100; + if (checknum < 0) checknum = 0; + const nblock = latest.number - checknum; + web3.eth.getBlock(checknum, (err, block) => { + if (err || !block) { + console.error(`StatsWeb3 error :${err}`); + res.write(JSON.stringify({ + 'blockHeight': latest.number, 'difficulty': latest.difficulty, 'blockTime': 0, 'hashrate': 0, + })); } else { - console.log("StatsWeb3: check block: " + block.number); - var blocktime = (latest.timestamp - block.timestamp) / nblock; - var hashrate = latest.difficulty / blocktime; - res.write(JSON.stringify({"blockHeight": latest.number, "difficulty": latest.difficulty, "blockTime": blocktime, "hashrate": hashrate })); + console.log(`StatsWeb3: check block: ${block.number}`); + const blocktime = (latest.timestamp - block.timestamp) / nblock; + const hashrate = latest.difficulty / blocktime; + res.write(JSON.stringify({ + 'blockHeight': latest.number, 'difficulty': latest.difficulty, 'blockTime': blocktime, 'hashrate': hashrate, + })); } res.end(); }); } }); } else { - console.error("Invalid Request: " + action) + console.error(`Invalid Request: ${action}`); res.status(400).send(); } } else { - console.error("Invalid Request: " + action) + console.error(`Invalid Request: ${action}`); res.status(400).send(); } diff --git a/tools/richlist.js b/tools/richlist.js index d59f823ab..ec63e9d4e 100644 --- a/tools/richlist.js +++ b/tools/richlist.js @@ -3,22 +3,22 @@ * Tool for calculating richlist by hackyminer */ -var _ = require('lodash'); -var Web3 = require('web3'); -var web3explorer = require('web3-explorer'); -var asyncL = require('async'); -var BigNumber = require('bignumber.js'); -var mongoose = require('mongoose'); +const _ = require('lodash'); +const Web3 = require('web3'); +const web3explorer = require('web3-explorer'); +const asyncL = require('async'); +const BigNumber = require('bignumber.js'); +const mongoose = require('mongoose'); -var Account = require('../db.js').Account; -var Transaction = require('../db.js').Transaction; -var Block = require('../db.js').Block; +const { Account } = require('../db.js'); +const { Transaction } = require('../db.js'); +const { Block } = require('../db.js'); const ADDRESS_CACHE_MAX = 10000; // address cache threshold // RichList for Geth Classic, Geth function makeRichList(toBlock, blocks, updateCallback) { - var self = makeRichList; + const self = makeRichList; if (!self.cached) { self.cached = {}; self.index = 0; @@ -26,33 +26,33 @@ function makeRichList(toBlock, blocks, updateCallback) { if (!self.accounts) { self.accounts = {}; } - var fromBlock = toBlock - blocks; + let fromBlock = toBlock - blocks; if (fromBlock < 0) { fromBlock = 0; } - console.log('Scan accounts from ' + fromBlock + ' to ' + toBlock + ' ...'); + console.log(`Scan accounts from ${fromBlock} to ${toBlock} ...`); - var ended = false; + let ended = false; if (fromBlock == toBlock) { ended = true; } asyncL.waterfall([ - function(callback) { + function (callback) { // Transaction.distinct("from", { blockNumber: { $lte: toBlock, $gt: fromBlock } }, function(err, docs) ... // faster // dictint("from") Transaction.aggregate([ { $match: { blockNumber: { $lte: toBlock, $gt: fromBlock } } }, - { $group: { _id: '$from' }}, - { $project: { "_id": 1 }} - ]).exec(function(err, docs) { + { $group: { _id: '$from' } }, + { $project: { '_id': 1 } }, + ]).exec((err, docs) => { if (err) { console.log(err); return; } - docs.forEach(function(doc) { + docs.forEach((doc) => { // check address cache if (!self.cached[doc._id]) { self.accounts[doc._id] = { address: doc._id, type: 0 }; @@ -64,18 +64,18 @@ function makeRichList(toBlock, blocks, updateCallback) { }); callback(null); }); - }, function(callback) { + }, function (callback) { // dictint("to") Transaction.aggregate([ { $match: { blockNumber: { $lte: toBlock, $gt: fromBlock } } }, - { $group: { _id: '$to' }}, - { $project: { "_id": 1 }} - ]).exec(function(err, docs) { + { $group: { _id: '$to' } }, + { $project: { '_id': 1 } }, + ]).exec((err, docs) => { if (err) { - console.log(err); - return; + console.log(err); + return; } - docs.forEach(function(doc) { + docs.forEach((doc) => { // to == null case if (!doc._id) { return; @@ -89,18 +89,18 @@ function makeRichList(toBlock, blocks, updateCallback) { }); callback(null); }); - }, function(callback) { + }, function (callback) { // aggregate miner's addresses Block.aggregate([ { $match: { number: { $lte: toBlock, $gt: fromBlock } } }, - { $group: { _id: '$miner' }}, - { $project: { "_id": 1 }} - ]).exec(function(err, docs) { + { $group: { _id: '$miner' } }, + { $project: { '_id': 1 } }, + ]).exec((err, docs) => { if (err) { - console.log(err); - return; + console.log(err); + return; } - docs.forEach(function(doc) { + docs.forEach((doc) => { if (!self.cached[doc._id]) { self.accounts[doc._id] = { address: doc._id, type: 0 }; self.cached[doc._id] = 1; @@ -110,30 +110,30 @@ function makeRichList(toBlock, blocks, updateCallback) { }); callback(null); }); - }, function(callback) { - let len = Object.keys(self.accounts).length; - console.info('* ' + len + ' / ' + (self.index + len) + ' total accounts.'); + }, function (callback) { + const len = Object.keys(self.accounts).length; + console.info(`* ${len} / ${self.index + len} total accounts.`); if (updateCallback && (len >= 100 || ended)) { self.index += len; - console.log("* update " + len + " accounts ..."); + console.log(`* update ${len} accounts ...`); // split accounts into chunks to make proper sized json-rpc batch job. - var accounts = Object.keys(self.accounts); - var chunks = []; + const accounts = Object.keys(self.accounts); + const chunks = []; // about ~1000 `eth_getBalance` json rpc calls are possible in one json-rpc batchjob. while (accounts.length > 200) { - var chunk = accounts.splice(0, 100); + const chunk = accounts.splice(0, 100); chunks.push(chunk); } if (accounts.length > 0) { chunks.push(accounts); } - asyncL.eachSeries(chunks, function(chunk, outerCallback) { - var data = {}; - asyncL.eachSeries(chunk, function(account, eachCallback) { - web3.eth.getCode(account, function(err, code) { + asyncL.eachSeries(chunks, (chunk, outerCallback) => { + const data = {}; + asyncL.eachSeries(chunk, (account, eachCallback) => { + web3.eth.getCode(account, (err, code) => { if (err) { return eachCallback(err); } @@ -144,7 +144,7 @@ function makeRichList(toBlock, blocks, updateCallback) { data[account].type = self.accounts[account].type; } - web3.eth.getBalance(account, function(err, balance) { + web3.eth.getBalance(account, (err, balance) => { if (err) { return eachCallback(err); } @@ -153,7 +153,7 @@ function makeRichList(toBlock, blocks, updateCallback) { eachCallback(); }); }); - }, function(err) { + }, (err) => { if (err) { return outerCallback(err); } @@ -163,22 +163,21 @@ function makeRichList(toBlock, blocks, updateCallback) { outerCallback(); }); - }, function(error) { + }, (error) => { if (error) { - console.log("WARN: fail to call getBalance() " + error); + console.log(`WARN: fail to call getBalance() ${error}`); } // reset accounts self.accounts = {}; // check the size of the cached accounts if (Object.keys(self.cached).length > ADDRESS_CACHE_MAX) { - console.info("** reduce cached accounts ..."); - var sorted = Object.keys(self.cached).sort(function(a, b) { - return self.cached[b] - self.cached[a]; // descend order - }); - var newcached = {}; - var reduce = parseInt(ADDRESS_CACHE_MAX * 0.6); - for (var j = 0; j < reduce; j++) { + console.info('** reduce cached accounts ...'); + const sorted = Object.keys(self.cached).sort((a, b) => self.cached[b] - self.cached[a], // descend order + ); + const newcached = {}; + const reduce = parseInt(ADDRESS_CACHE_MAX * 0.6); + for (let j = 0; j < reduce; j++) { newcached[sorted[j]] = self.cached[sorted[j]]; } self.cached = newcached; @@ -189,17 +188,17 @@ function makeRichList(toBlock, blocks, updateCallback) { } else { callback(null); } - } - ], function(error) { + }, + ], (error) => { if (error) { console.log(error); return; } if (ended) { - console.log("**DONE**"); + console.log('**DONE**'); } else { - setTimeout(function() { + setTimeout(() => { makeRichList(fromBlock, blocks, updateCallback); }, 300); } @@ -207,7 +206,7 @@ function makeRichList(toBlock, blocks, updateCallback) { } function makeParityRichList(number, offset, blockNumber, updateCallback) { - var self = makeParityRichList; + const self = makeParityRichList; if (!self.index) { self.index = 0; } @@ -215,33 +214,33 @@ function makeParityRichList(number, offset, blockNumber, updateCallback) { offset = offset || null; asyncL.waterfall([ - function(callback) { - web3.parity.listAccounts(number, offset, blockNumber, function(err, result) { + function (callback) { + web3.parity.listAccounts(number, offset, blockNumber, (err, result) => { callback(err, result); }); - }, function(accounts, callback) { + }, function (accounts, callback) { if (!accounts) { return callback({ error: true, - message: "No accounts found. Please restart Parity with --fat-db=on option to enable FatDB." + message: 'No accounts found. Please restart Parity with --fat-db=on option to enable FatDB.', }); } if (accounts.length === 0) { return callback({ error: true, - message: "No more accounts found." + message: 'No more accounts found.', }); } - var lastAccount = accounts[accounts.length - 1]; - var data = {}; + const lastAccount = accounts[accounts.length - 1]; + const data = {}; // Please see https://github.com/gobitfly/etherchain-light by gobitfly - asyncL.eachSeries(accounts, function(account, eachCallback) { - web3.eth.getCode(account, function(err, code) { + asyncL.eachSeries(accounts, (account, eachCallback) => { + web3.eth.getCode(account, (err, code) => { if (err) { - console.log("ERROR: fail to getCode(" + account + ")"); + console.log(`ERROR: fail to getCode(${account})`); return eachCallback(err); } data[account] = {}; @@ -251,9 +250,9 @@ function makeParityRichList(number, offset, blockNumber, updateCallback) { data[account].type = 1; //contract case } - web3.eth.getBalance(account, function(err, balance) { + web3.eth.getBalance(account, (err, balance) => { if (err) { - console.log("ERROR: fail to getBalance(" + account + ")"); + console.log(`ERROR: fail to getBalance(${account})`); return eachCallback(err); } @@ -261,11 +260,11 @@ function makeParityRichList(number, offset, blockNumber, updateCallback) { eachCallback(); }); }); - }, function(err) { + }, (err) => { callback(err, data, lastAccount); }); - } - ], function(error, accounts, lastAccount) { + }, + ], (error, accounts, lastAccount) => { if (error) { console.log(error); process.exit(9); @@ -274,13 +273,13 @@ function makeParityRichList(number, offset, blockNumber, updateCallback) { //console.log(JSON.stringify(accounts, null, 2)); offset = lastAccount; - let j = Object.keys(accounts).length; + const j = Object.keys(accounts).length; self.index += j; - console.log(' * ' + j + ' / ' + self.index + ' accounts, offset = ' + offset); + console.log(` * ${j} / ${self.index} accounts, offset = ${offset}`); if (updateCallback) { updateCallback(accounts, blockNumber); } - setTimeout(function() { + setTimeout(() => { makeParityRichList(number, lastAccount, blockNumber, updateCallback); }, 300); }); @@ -289,33 +288,33 @@ function makeParityRichList(number, offset, blockNumber, updateCallback) { /** * Write accounts to DB */ -var updateAccounts = function(accounts, blockNumber) { +const updateAccounts = function (accounts, blockNumber) { // prepare - var bulk = Object.keys(accounts).map(function(j) { - let account = accounts[j]; + const bulk = Object.keys(accounts).map((j) => { + const account = accounts[j]; account.blockNumber = blockNumber; return account; }); bulkInsert(bulk); -} +}; -var bulkInsert = function(bulk) { +var bulkInsert = function (bulk) { if (!bulk.length) { return; } - var localbulk; + let localbulk; if (bulk.length > 300) { localbulk = bulk.splice(0, 200); } else { localbulk = bulk.splice(0, 300); } - Account.collection.insert(localbulk, function(error, data) { + Account.collection.insert(localbulk, (error, data) => { if (error) { if (error.code == 11000) { // For already exists case, try upsert method. - asyncL.eachSeries(localbulk, function(item, eachCallback) { + asyncL.eachSeries(localbulk, (item, eachCallback) => { // upsert accounts item._id = undefined; delete item._id; // remove _id field @@ -324,94 +323,94 @@ var bulkInsert = function(bulk) { item.type = undefined; delete item.type; } - Account.collection.update({ "address": item.address }, { $set: item }, { upsert: true }, function(err, updated) { + Account.collection.update({ 'address': item.address }, { $set: item }, { upsert: true }, (err, updated) => { if (err) { if (!config.quiet) { - console.log('WARN: Duplicate DB key : ' + error); - console.log('ERROR: Fail to update account: ' + err); + console.log(`WARN: Duplicate DB key : ${error}`); + console.log(`ERROR: Fail to update account: ${err}`); } return eachCallback(err); } eachCallback(); }); - }, function(err) { + }, (err) => { if (err) { if (err.code != 11000) { - console.log('ERROR: Aborted due to error: ' + JSON.stringify(err, null, 2)); + console.log(`ERROR: Aborted due to error: ${JSON.stringify(err, null, 2)}`); process.exit(9); return; - } else { - console.log('WARN: Fail to upsert (ignore) ' + err); } + console.log(`WARN: Fail to upsert (ignore) ${err}`); + } - console.log('* ' + localbulk.length + ' accounts successfully updated.'); + console.log(`* ${localbulk.length} accounts successfully updated.`); if (bulk.length > 0) { - setTimeout(function() { + setTimeout(() => { bulkInsert(bulk); }, 200); } }); } else { - console.log('Error: Aborted due to error on DB: ' + error); + console.log(`Error: Aborted due to error on DB: ${error}`); process.exit(9); } } else { - console.log('* ' + data.insertedCount + ' accounts successfully inserted.'); + console.log(`* ${data.insertedCount} accounts successfully inserted.`); if (bulk.length > 0) { - setTimeout(function() { + setTimeout(() => { bulkInsert(bulk); }, 200); } } }); -} +}; function prepareJsonAddress(json, defaultType = 0) { - var accounts = {}; + const accounts = {}; if (json.accounts) { // genesis.json style - Object.keys(json.accounts).forEach(function(account) { - var key = account.toLowerCase(); - key = '0x' + key.replace(/^0x/, ''); - accounts[key] = { address: key, type: type }; + Object.keys(json.accounts).forEach((account) => { + let key = account.toLowerCase(); + key = `0x${key.replace(/^0x/, '')}`; + accounts[key] = { address: key, type }; }); } else if (typeof json === 'object') { - Object.keys(json).forEach(function(account) { - var key = account.toLowerCase(); - key = '0x' + key.replace(/^0x/, ''); - var type = defaultType; + Object.keys(json).forEach((account) => { + let key = account.toLowerCase(); + key = `0x${key.replace(/^0x/, '')}`; + let type = defaultType; if (json[account].type) { type = json[account].type; } - accounts[key] = { address: key, type: type }; + accounts[key] = { address: key, type }; }); } else { // normal array - json.forEach(function(account) { - var key = account.toLowerCase(); - key = '0x' + key.replace(/^0x/, ''); - accounts[key] = { address: key, type: type }; + json.forEach((account) => { + let key = account.toLowerCase(); + key = `0x${key.replace(/^0x/, '')}`; + accounts[key] = { address: key, type }; }); } return accounts; } function readJsonAccounts(json, blockNumber, callback, defaultType = 0) { - var data = prepareJsonAddress(json, defaultType); - var accounts = Object.keys(data); - console.log("* update " + accounts.length + " genesis accounts..."); - async.eachSeries(accounts, function(account, eachCallback) { - web3.eth.getBalance(account, function(err, balance) { + const data = prepareJsonAddress(json, defaultType); + const accounts = Object.keys(data); + console.log(`* update ${accounts.length} genesis accounts...`); + async.eachSeries(accounts, (account, eachCallback) => { + web3.eth.getBalance(account, (err, balance) => { if (err) { - console.log("ERROR: fail to getBalance(" + account + ")"); + console.log(`ERROR: fail to getBalance(${account})`); return eachCallback(err); } data[account].balance = parseFloat(web3.utils.fromWei(balance, 'ether')); eachCallback(); }); - }, function(err) { + }, (err) => { if (err) { - console.log("ERROR: fail to getBalance()" + err); + console.log(`ERROR: fail to getBalance()${err}`); return; } callback(data, blockNumber); @@ -424,7 +423,7 @@ function readJsonAccounts(json, blockNumber, callback, defaultType = 0) { var config = { nodeAddr: 'localhost', 'wsPort': 8546 }; // load the config.json file try { - var loaded = require('../config.json'); + const loaded = require('../config.json'); _.extend(config, loaded); console.log('config.json found.'); } catch (error) { @@ -437,29 +436,29 @@ try { //config.quiet = false; //mongoose.set('debug', true); -console.log('Connecting ' + config.nodeAddr + ':' + config.wsPort + '...'); +console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); -var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://' + config.nodeAddr + ':' + config.wsPort.toString())); +var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); async function startSync() { - var latestBlock = await web3.eth.getBlockNumber(); - var nodeInfo = await web3.eth.getNodeInfo(); + const latestBlock = await web3.eth.getBlockNumber(); + const nodeInfo = await web3.eth.getNodeInfo(); - console.log("Node version = " + nodeInfo); + console.log(`Node version = ${nodeInfo}`); if (nodeInfo.split('/')[0].toLowerCase().includes('parity')) { - console.log("Web3 has detected parity node configuration"); + console.log('Web3 has detected parity node configuration'); web3explorer(web3); - console.log("* latestBlock = " + latestBlock); + console.log(`* latestBlock = ${latestBlock}`); makeParityRichList(500, null, latestBlock, updateAccounts); } else { // load genesis account if (config.settings && config.settings.genesisAddress) { try { - var genesis = require('../' + config.settings.genesisAddress); + const genesis = require(`../${config.settings.genesisAddress}`); readJsonAccounts(genesis, latestBlock, updateAccounts); } catch (e) { - console.log("Error: Fail to load genesis address (ignore)"); + console.log('Error: Fail to load genesis address (ignore)'); } } makeRichList(latestBlock, 500, updateAccounts); diff --git a/tools/stats.js b/tools/stats.js index 96e4f4413..56f928eff 100644 --- a/tools/stats.js +++ b/tools/stats.js @@ -2,117 +2,111 @@ Tool for calculating block stats */ -var _ = require('lodash'); -var Web3 = require('web3'); - -var mongoose = require( 'mongoose' ); -var BlockStat = require( '../db.js' ).BlockStat; - -var updateStats = async (range, interval, rescan) => { - var latestBlock = await web3.eth.getBlockNumber(); - - interval = Math.abs(parseInt(interval)); - if (!range) { - range = 1000; - } - range *= interval; - if (interval >= 10) { - latestBlock -= latestBlock % interval; +const _ = require('lodash'); +const Web3 = require('web3'); + +const mongoose = require('mongoose'); +const { BlockStat } = require('../db.js'); + +const updateStats = async (range, interval, rescan) => { + let latestBlock = await web3.eth.getBlockNumber(); + + interval = Math.abs(parseInt(interval)); + if (!range) { + range = 1000; + } + range *= interval; + if (interval >= 10) { + latestBlock -= latestBlock % interval; + } + getStats(web3, latestBlock, null, latestBlock - range, interval, rescan); +}; + +var getStats = function (web3, blockNumber, nextBlock, endNumber, interval, rescan) { + if (endNumber < 0) endNumber = 0; + if (blockNumber <= endNumber) { + if (rescan) { + process.exit(9); } - getStats(web3, latestBlock, null, latestBlock - range, interval, rescan); -} - - -var getStats = function(web3, blockNumber, nextBlock, endNumber, interval, rescan) { - if (endNumber < 0) - endNumber = 0; - if (blockNumber <= endNumber) { - if (rescan) { - process.exit(9); - } - return; - } - - if(web3.eth.net.isListening()) { - - web3.eth.getBlock(blockNumber, true, function(error, blockData) { - if(error) { - console.log('Warning: error on getting block with hash/number: ' + - blockNumber + ': ' + error); - } - else if(blockData == null) { - console.log('Warning: null block data received from the block with hash/number: ' + - blockNumber); - } - else { - if (nextBlock) - checkBlockDBExistsThenWrite(web3, blockData, nextBlock, endNumber, interval, rescan); - else - checkBlockDBExistsThenWrite(web3, blockData, null, endNumber, interval, rescan); - } - }); - } else { - console.log('Error: Aborted due to web3 is not connected when trying to ' + - 'get block ' + blockNumber); - process.exit(9); - } -} + return; + } + + if (web3.eth.net.isListening()) { + + web3.eth.getBlock(blockNumber, true, (error, blockData) => { + if (error) { + console.log(`Warning: error on getting block with hash/number: ${ + blockNumber}: ${error}`); + } else if (blockData == null) { + console.log(`Warning: null block data received from the block with hash/number: ${ + blockNumber}`); + } else { + if (nextBlock) checkBlockDBExistsThenWrite(web3, blockData, nextBlock, endNumber, interval, rescan); + else checkBlockDBExistsThenWrite(web3, blockData, null, endNumber, interval, rescan); + } + }); + } else { + console.log(`${'Error: Aborted due to web3 is not connected when trying to ' + + 'get block '}${blockNumber}`); + process.exit(9); + } +}; /** * Checks if the a record exists for the block number * if record exists: abort * if record DNE: write a file for the block */ -var checkBlockDBExistsThenWrite = function(web3, blockData, nextBlock, endNumber, interval, rescan) { - BlockStat.find({number: blockData.number}, function (err, b) { - if (!b.length && nextBlock) { - // calc hashrate, txCount, blocktime, uncleCount - var stat = { - "number": blockData.number, - "timestamp": blockData.timestamp, - "difficulty": blockData.difficulty, - "txCount": blockData.transactions.length, - "gasUsed": blockData.gasUsed, - "gasLimit": blockData.gasLimit, - "miner": blockData.miner, - "blockTime": (nextBlock.timestamp - blockData.timestamp) / (nextBlock.number - blockData.number), - "uncleCount": blockData.uncles.length - } - new BlockStat(stat).save( function( err, s, count ){ - console.log(s) - if ( typeof err !== 'undefined' && err ) { - console.log('Error: Aborted due to error on ' + - 'block number ' + blockData.number.toString() + ': ' + - err); - process.exit(9); - } else { - console.log('DB successfully written for block number ' + - blockData.number.toString() ); - getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan); - } - }); +var checkBlockDBExistsThenWrite = function (web3, blockData, nextBlock, endNumber, interval, rescan) { + BlockStat.find({ number: blockData.number }, (err, b) => { + if (!b.length && nextBlock) { + // calc hashrate, txCount, blocktime, uncleCount + const stat = { + 'number': blockData.number, + 'timestamp': blockData.timestamp, + 'difficulty': blockData.difficulty, + 'txCount': blockData.transactions.length, + 'gasUsed': blockData.gasUsed, + 'gasLimit': blockData.gasLimit, + 'miner': blockData.miner, + 'blockTime': (nextBlock.timestamp - blockData.timestamp) / (nextBlock.number - blockData.number), + 'uncleCount': blockData.uncles.length, + }; + new BlockStat(stat).save((err, s, count) => { + console.log(s); + if (typeof err !== 'undefined' && err) { + console.log(`${'Error: Aborted due to error on ' + + 'block number '}${blockData.number.toString()}: ${ + err}`); + process.exit(9); } else { - if (rescan || !nextBlock) { - getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan); - if (nextBlock) { - console.log('WARN: block number: ' + blockData.number.toString() + ' already exists in DB.'); - } - } else { - console.error('Aborting because block number: ' + blockData.number.toString() + - ' already exists in DB.'); - return; - } + console.log(`DB successfully written for block number ${ + blockData.number.toString()}`); + getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan); } + }); + } else { + if (rescan || !nextBlock) { + getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan); + if (nextBlock) { + console.log(`WARN: block number: ${blockData.number.toString()} already exists in DB.`); + } + } else { + console.error(`Aborting because block number: ${blockData.number.toString() + } already exists in DB.`); - }) -} + } + } + + }); +}; -var minutes = 1; +const minutes = 1; statInterval = minutes * 60 * 1000; -var rescan = false; /* rescan: true - rescan range */ -var range = 1000; -var interval = 100; +let rescan = false; /* rescan: true - rescan range */ +let range = 1000; +let interval = 100; /** * RESCAN=1000:100000 means interval;range @@ -121,50 +115,50 @@ var interval = 100; * RESCAN=1000:100000 node tools/stats.js */ if (process.env.RESCAN) { - var tmp = process.env.RESCAN.split(/:/); - if (tmp.length > 1) { - interval = Math.abs(parseInt(tmp[0])); - if (tmp[1]) { - range = Math.abs(parseInt(tmp[1])); - } + const tmp = process.env.RESCAN.split(/:/); + if (tmp.length > 1) { + interval = Math.abs(parseInt(tmp[0])); + if (tmp[1]) { + range = Math.abs(parseInt(tmp[1])); } - var i = interval; - var j = 0; - for (var j = 0; i >= 10; j++) { - i = parseInt(i / 10); - } - interval = Math.pow(10, j); - console.log('Selected interval = ' + interval); - - rescan = true; + } + let i = interval; + var j = 0; + for (var j = 0; i >= 10; j++) { + i = parseInt(i / 10); + } + interval = Math.pow(10, j); + console.log(`Selected interval = ${interval}`); + + rescan = true; } // load config.json -var config = { nodeAddr: 'localhost', wsPort: 8546, bulkSize: 100 }; +const config = { nodeAddr: 'localhost', wsPort: 8546, bulkSize: 100 }; try { - var local = require('../config.json'); - _.extend(config, local); - console.log('config.json found.'); + 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); - } + 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); + } } -console.log('Connecting ' + config.nodeAddr + ':' + config.wsPort + '...'); +console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); -var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://' + config.nodeAddr + ':' + config.wsPort.toString())); +var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); // run updateStats(range, interval, rescan); if (!rescan) { - setInterval(function() { - updateStats(range, interval); - }, statInterval); + setInterval(() => { + updateStats(range, interval); + }, statInterval); } diff --git a/tools/sync.js b/tools/sync.js index c2a4b9d9c..4606d3743 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -4,38 +4,61 @@ Version: .0.0.2 This file will start syncing the blockchain from the node address you provide in the conf.json file. Please read the README in the root directory that explains the parameters of this code */ -require( '../db.js' ); -var etherUnits = require("../lib/etherUnits.js"); -var BigNumber = require('bignumber.js'); -var _ = require('lodash'); - -var asyncL = require('async'); -var Web3 = require('web3'); - -const fetch = require("node-fetch"); -const Market = require( '../db.js' ).Market; - -var mongoose = require( 'mongoose' ); -var Block = mongoose.model( 'Block' ); -var Transaction = mongoose.model( 'Transaction' ); -var Account = mongoose.model( 'Account' ); -var Contract = mongoose.model( 'Contract' ); -var TokenTransfer = mongoose.model( 'TokenTransfer' ); - -const ERC20ABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]; -const ERC20_METHOD_DIC = {"0xa9059cbb":"transfer", "0xa978501e":"transferFrom"}; +require('../db.js'); +const BigNumber = require('bignumber.js'); +const _ = require('lodash'); + +const asyncL = require('async'); +const Web3 = require('web3'); + +const fetch = require('node-fetch'); + +const mongoose = require('mongoose'); +const etherUnits = require('../lib/etherUnits.js'); +const { Market } = require('../db.js'); + +const Block = mongoose.model('Block'); +const Transaction = mongoose.model('Transaction'); +const Account = mongoose.model('Account'); +const Contract = mongoose.model('Contract'); +const TokenTransfer = mongoose.model('TokenTransfer'); + +const ERC20ABI = [{ + 'constant': true, 'inputs': [], 'name': 'name', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', +}, { + 'constant': false, 'inputs': [{ 'name': '_spender', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'approve', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function', +}, { + 'constant': true, 'inputs': [], 'name': 'totalSupply', 'outputs': [{ 'name': '', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', +}, { + 'constant': false, 'inputs': [{ 'name': '_from', 'type': 'address' }, { 'name': '_to', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'transferFrom', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function', +}, { + 'constant': true, 'inputs': [], 'name': 'decimals', 'outputs': [{ 'name': '', 'type': 'uint8' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', +}, { + 'constant': true, 'inputs': [{ 'name': '_owner', 'type': 'address' }], 'name': 'balanceOf', 'outputs': [{ 'name': 'balance', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', +}, { + 'constant': true, 'inputs': [], 'name': 'symbol', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', +}, { + 'constant': false, 'inputs': [{ 'name': '_to', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'transfer', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function', +}, { + 'constant': true, 'inputs': [{ 'name': '_owner', 'type': 'address' }, { 'name': '_spender', 'type': 'address' }], 'name': 'allowance', 'outputs': [{ 'name': '', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', +}, { 'payable': true, 'stateMutability': 'payable', 'type': 'fallback' }, { + 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'owner', 'type': 'address' }, { 'indexed': true, 'name': 'spender', 'type': 'address' }, { 'indexed': false, 'name': 'value', 'type': 'uint256' }], 'name': 'Approval', 'type': 'event', +}, { + 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'from', 'type': 'address' }, { 'indexed': true, 'name': 'to', 'type': 'address' }, { 'indexed': false, 'name': 'value', 'type': 'uint256' }], 'name': 'Transfer', 'type': 'event', +}]; +const ERC20_METHOD_DIC = { '0xa9059cbb': 'transfer', '0xa978501e': 'transferFrom' }; const METHOD_DIC = { - "0x930a61a57a70a73c2a503615b87e2e54fe5b9cdeacda518270b852296ab1a377":"Transfer(address,address,uint)", - "0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b":"transfer(address,uint256)", - "0xa978501e4506ecbd340f6e45a48ac5bd126b1c14f03f2210837c8e0b602d4d7b":"transferFrom(address,address,uint)", - "0x086c40f692cc9c13988b9e49a7610f67375e8373bfe7653911770b351c2b1c54":"approve(address,uint)", - "0xf2fde38b092330466c661fc723d5289b90272a3e580e3187d1d7ef788506c557":"transferOwnership(address)", - "0x3bc50cfd0fe2c05fb67c0fe4be91fb10eb723ba30ea8f559d533fcd5fe29be7f":"Released(address,uint)", - "0xb21fb52d5749b80f3182f8c6992236b5e5576681880914484d7f4c9b062e619e":"Released(address indexed, uint indexed)" + '0x930a61a57a70a73c2a503615b87e2e54fe5b9cdeacda518270b852296ab1a377': 'Transfer(address,address,uint)', + '0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b': 'transfer(address,uint256)', + '0xa978501e4506ecbd340f6e45a48ac5bd126b1c14f03f2210837c8e0b602d4d7b': 'transferFrom(address,address,uint)', + '0x086c40f692cc9c13988b9e49a7610f67375e8373bfe7653911770b351c2b1c54': 'approve(address,uint)', + '0xf2fde38b092330466c661fc723d5289b90272a3e580e3187d1d7ef788506c557': 'transferOwnership(address)', + '0x3bc50cfd0fe2c05fb67c0fe4be91fb10eb723ba30ea8f559d533fcd5fe29be7f': 'Released(address,uint)', + '0xb21fb52d5749b80f3182f8c6992236b5e5576681880914484d7f4c9b062e619e': 'Released(address indexed, uint indexed)', }; const normalizeTX = async (txData, receipt, blockData) => { - var tx = { + const tx = { blockHash: txData.blockHash, blockNumber: txData.blockNumber, from: txData.from.toLowerCase(), @@ -50,60 +73,58 @@ const normalizeTX = async (txData, receipt, blockData) => { gasPrice: String(txData.gasPrice), input: txData.input, transactionIndex: txData.transactionIndex, - timestamp: blockData.timestamp + timestamp: blockData.timestamp, }; - if (receipt.status) - tx.status = receipt.status; + if (receipt.status) tx.status = receipt.status; if (txData.to) { tx.to = txData.to.toLowerCase(); return tx; - } else { - if (tx.creates) { - tx.creates = txData.creates.toLowerCase(); - return tx; - } else { - if (receipt && receipt.contractAddress) { - tx.creates = receipt.contractAddress.toLowerCase(); - } - return tx; - } } -} + if (tx.creates) { + tx.creates = txData.creates.toLowerCase(); + return tx; + } + if (receipt && receipt.contractAddress) { + tx.creates = receipt.contractAddress.toLowerCase(); + } + return tx; + +}; /** //Just listen for latest blocks and sync from the start of the app. **/ -var listenBlocks = function(config) { - var newBlocks = web3.eth.subscribe('newBlockHeaders', function(error, result){ - if (!error) { - return; - } +const listenBlocks = function (config) { + const newBlocks = web3.eth.subscribe('newBlockHeaders', (error, result) => { + if (!error) { + return; + } - console.error(error); - }); - newBlocks.on("data", function (blockHeader) { - web3.eth.getBlock(blockHeader.hash, true, function(error, blockData) { - if (blockHeader == null) { - console.log('Warning: null block hash'); - } else { - writeBlockToDB(config, blockData, true); - writeTransactionsToDB(config, blockData, true); - } - }); + console.error(error); + }); + newBlocks.on('data', (blockHeader) => { + web3.eth.getBlock(blockHeader.hash, true, (error, blockData) => { + if (blockHeader == null) { + console.log('Warning: null block hash'); + } else { + writeBlockToDB(config, blockData, true); + writeTransactionsToDB(config, blockData, true); + } }); - newBlocks.on("error", console.error); -} + }); + newBlocks.on('error', console.error); +}; /** If full sync is checked this function will start syncing the block chain from lastSynced param see README **/ -var syncChain = function(config, nextBlock){ - if(web3.eth.net.isListening()) { +var syncChain = function (config, nextBlock) { + if (web3.eth.net.isListening()) { if (typeof nextBlock === 'undefined') { - prepareSync(config, function(error, startBlock) { - if(error) { - console.log('ERROR: error: ' + error); + prepareSync(config, (error, startBlock) => { + if (error) { + console.log(`ERROR: error: ${error}`); return; } syncChain(config, startBlock); @@ -111,10 +132,10 @@ var syncChain = function(config, nextBlock){ return; } - if( nextBlock == null ) { + if (nextBlock == null) { console.log('nextBlock is null'); return; - } else if( nextBlock < config.startBlock ) { + } if (nextBlock < config.startBlock) { writeBlockToDB(config, null, true); writeTransactionsToDB(config, null, true); console.log('*** Sync Finsihed ***'); @@ -122,14 +143,14 @@ var syncChain = function(config, nextBlock){ return; } - var count = config.bulkSize; - while(nextBlock >= config.startBlock && count > 0) { - web3.eth.getBlock(nextBlock, true, function(error,blockData) { - if(error) { - console.log('Warning (syncChain): error on getting block with hash/number: ' + nextBlock + ': ' + error); - }else if(blockData == null) { - console.log('Warning: null block data received from the block with hash/number: ' + nextBlock); - }else{ + let count = config.bulkSize; + while (nextBlock >= config.startBlock && count > 0) { + web3.eth.getBlock(nextBlock, true, (error, blockData) => { + if (error) { + console.log(`Warning (syncChain): error on getting block with hash/number: ${nextBlock}: ${error}`); + } else if (blockData == null) { + console.log(`Warning: null block data received from the block with hash/number: ${nextBlock}`); + } else { writeBlockToDB(config, blockData); writeTransactionsToDB(config, blockData); } @@ -138,55 +159,55 @@ var syncChain = function(config, nextBlock){ count--; } - setTimeout(function() { syncChain(config, nextBlock); }, 500); - }else{ - console.log('Error: Web3 connection time out trying to get block ' + nextBlock + ' retrying connection now'); + setTimeout(() => { syncChain(config, nextBlock); }, 500); + } else { + console.log(`Error: Web3 connection time out trying to get block ${nextBlock} retrying connection now`); syncChain(config, nextBlock); } -} +}; /** Write the whole block object to DB **/ -var writeBlockToDB = function(config, blockData, flush) { - var self = writeBlockToDB; +var writeBlockToDB = function (config, blockData, flush) { + const self = writeBlockToDB; if (!self.bulkOps) { self.bulkOps = []; } if (blockData && blockData.number >= 0) { self.bulkOps.push(new Block(blockData)); - if(!('quiet' in config && config.quiet === true)) { - console.log('\t- block #' + blockData.number.toString() + ' inserted.'); + if (!('quiet' in config && config.quiet === true)) { + console.log(`\t- block #${blockData.number.toString()} inserted.`); } } - if(flush && self.bulkOps.length > 0 || self.bulkOps.length >= config.bulkSize) { - var bulk = self.bulkOps; + if (flush && self.bulkOps.length > 0 || self.bulkOps.length >= config.bulkSize) { + const bulk = self.bulkOps; self.bulkOps = []; - if(bulk.length == 0) return; + if (bulk.length == 0) return; - Block.collection.insert(bulk, function( err, blocks ){ - if ( typeof err !== 'undefined' && err ) { + Block.collection.insert(bulk, (err, blocks) => { + if (typeof err !== 'undefined' && err) { if (err.code == 11000) { - if(!('quiet' in config && config.quiet === true)) { - console.log('Skip: Duplicate DB key : ' +err); + if (!('quiet' in config && config.quiet === true)) { + console.log(`Skip: Duplicate DB key : ${err}`); } - }else{ - console.log('Error: Aborted due to error on DB: ' + err); + } else { + console.log(`Error: Aborted due to error on DB: ${err}`); process.exit(9); } - }else{ - if(!('quiet' in config && config.quiet === true)) { - console.log('* ' + blocks.insertedCount + ' blocks successfully written.'); + } else { + if (!('quiet' in config && config.quiet === true)) { + console.log(`* ${blocks.insertedCount} blocks successfully written.`); } } }); } -} +}; /** Break transactions out of blocks and write to DB **/ -const writeTransactionsToDB = async(config, blockData, flush) => { - var self = writeTransactionsToDB; +const writeTransactionsToDB = async (config, blockData, flush) => { + const self = writeTransactionsToDB; if (!self.bulkOps) { self.bulkOps = []; self.blocks = 0; @@ -200,22 +221,22 @@ const writeTransactionsToDB = async(config, blockData, flush) => { } if (blockData && blockData.transactions.length > 0) { for (d in blockData.transactions) { - var txData = blockData.transactions[d]; - var receipt = await web3.eth.getTransactionReceipt(txData.hash); - var tx = await normalizeTX(txData, receipt, blockData); + const txData = blockData.transactions[d]; + const receipt = await web3.eth.getTransactionReceipt(txData.hash); + const tx = await normalizeTX(txData, receipt, blockData); // Contact creation tx, Event logs of internal transaction if (txData.input && txData.input.length > 2) { // Contact creation tx if (txData.to == null) { contractAddress = txData.creates.toLowerCase(); - var contractdb = {} - var isTokenContract = true; - var Token = new web3.eth.Contract(ERC20ABI, contractAddress); + const contractdb = {}; + let isTokenContract = true; + const Token = new web3.eth.Contract(ERC20ABI, contractAddress); contractdb.owner = txData.from; contractdb.blockNumber = blockData.number; contractdb.creationTransaction = txData.hash; try { - var call = await web3.eth.call({ to: contractAddress, data:web3.utils.sha3("totalSupply()")}); + const call = await web3.eth.call({ to: contractAddress, data: web3.utils.sha3('totalSupply()') }); if (call == '0x') { isTokenContract = false; } else { @@ -239,31 +260,33 @@ const writeTransactionsToDB = async(config, blockData, flush) => { contractdb.ERC = 0; } // Write to db - Contract.update ( - {address: contractAddress}, - {$setOnInsert: contractdb}, - {upsert: true}, - function (err, data) { + Contract.update( + { address: contractAddress }, + { $setOnInsert: contractdb }, + { upsert: true }, + (err, data) => { if (err) { console.log(err); } - } + }, ); } else { // Internal transaction . write to doc of InternalTx - var transfer = {"hash": "", "blockNumber": 0, "from": "", "to": "", "contract":"", "value": 0, "timestamp":0}; - var methodCode = txData.input.substr(0,10); - if (ERC20_METHOD_DIC[methodCode]=="transfer" || ERC20_METHOD_DIC[methodCode]=="transferFrom") { - if (ERC20_METHOD_DIC[methodCode]=="transfer") { + const transfer = { + 'hash': '', 'blockNumber': 0, 'from': '', 'to': '', 'contract': '', 'value': 0, 'timestamp': 0, + }; + const methodCode = txData.input.substr(0, 10); + if (ERC20_METHOD_DIC[methodCode] == 'transfer' || ERC20_METHOD_DIC[methodCode] == 'transferFrom') { + if (ERC20_METHOD_DIC[methodCode] == 'transfer') { // Token transfer transaction transfer.from = txData.from; - transfer.to = "0x" + txData.input.substring(34,74); - transfer.value = Number("0x" + txData.input.substring(74)); + transfer.to = `0x${txData.input.substring(34, 74)}`; + transfer.value = Number(`0x${txData.input.substring(74)}`); } else { // transferFrom - transfer.from = "0x" + txData.input.substring(34,74); - transfer.to = "0x" + txData.input.substring(74,114); - transfer.value = Number("0x" + txData.input.substring(114)); + transfer.from = `0x${txData.input.substring(34, 74)}`; + transfer.to = `0x${txData.input.substring(74, 114)}`; + transfer.value = Number(`0x${txData.input.substring(114)}`); } transfer.method = ERC20_METHOD_DIC[methodCode]; transfer.hash = txData.hash; @@ -271,37 +294,37 @@ const writeTransactionsToDB = async(config, blockData, flush) => { transfer.contract = txData.to; transfer.timestamp = blockData.timestamp; // Write transfer transaction into db - TokenTransfer.update ( - {hash: transfer.hash}, - {$setOnInsert: transfer}, - {upsert: true}, - function (err, data) { + TokenTransfer.update( + { hash: transfer.hash }, + { $setOnInsert: transfer }, + { upsert: true }, + (err, data) => { if (err) { console.log(err); } - } + }, ); } } } self.bulkOps.push(tx); } - if(!('quiet' in config && config.quiet === true)) { - console.log('\t- block #' + blockData.number.toString() + ': ' + blockData.transactions.length.toString() + ' transactions recorded.'); + if (!('quiet' in config && config.quiet === true)) { + console.log(`\t- block #${blockData.number.toString()}: ${blockData.transactions.length.toString()} transactions recorded.`); } } self.blocks++; if (flush && self.blocks > 0 || self.blocks >= config.bulkSize) { - var bulk = self.bulkOps; + const bulk = self.bulkOps; self.bulkOps = []; self.blocks = 0; - var miners = self.miners; + const { miners } = self; self.miners = []; // setup accounts - var data = {}; - bulk.forEach(function(tx) { + const data = {}; + bulk.forEach((tx) => { data[tx.from] = { address: tx.from, blockNumber: tx.blockNumber, type: 0 }; if (tx.to) { data[tx.to] = { address: tx.to, blockNumber: tx.blockNumber, type: 0 }; @@ -309,103 +332,105 @@ const writeTransactionsToDB = async(config, blockData, flush) => { }); // setup miners - miners.forEach(function(miner) { + miners.forEach((miner) => { data[miner.address] = miner; }); - var accounts = Object.keys(data); + const accounts = Object.keys(data); if (bulk.length == 0 && accounts.length == 0) return; // update balances - if (config.useRichList && accounts.length > 0) - asyncL.eachSeries(accounts, function(account, eachCallback) { - var blockNumber = data[account].blockNumber; - // get contract account type - web3.eth.getCode(account, function(err, code) { - if (err) { - console.log("ERROR: fail to getCode(" + account + ")"); - return eachCallback(err); - } - if (code.length > 2) { - data[account].type = 1; // contract type - } - - web3.eth.getBalance(account, blockNumber, function(err, balance) { + if (config.useRichList && accounts.length > 0) { + asyncL.eachSeries(accounts, (account, eachCallback) => { + const { blockNumber } = data[account]; + // get contract account type + web3.eth.getCode(account, (err, code) => { if (err) { - console.log(err); - console.log("ERROR: fail to getBalance(" + account + ")"); + console.log(`ERROR: fail to getCode(${account})`); return eachCallback(err); } + if (code.length > 2) { + data[account].type = 1; // contract type + } - data[account].balance = parseFloat(web3.utils.fromWei(balance, 'ether')); - eachCallback(); + web3.eth.getBalance(account, blockNumber, (err, balance) => { + if (err) { + console.log(err); + console.log(`ERROR: fail to getBalance(${account})`); + return eachCallback(err); + } + + data[account].balance = parseFloat(web3.utils.fromWei(balance, 'ether')); + eachCallback(); + }); + }); + }, (err) => { + let n = 0; + accounts.forEach((account) => { + n++; + if (n <= 5) { + console.log(` - upsert ${account} / balance = ${data[account].balance}`); + } else if (n == 6) { + console.log(` (...) total ${accounts.length} accounts updated.`); + } + // upsert account + Account.collection.update({ address: account }, { $set: data[account] }, { upsert: true }); }); }); - }, function(err) { - var n = 0; - accounts.forEach(function(account) { - n++; - if (n <= 5) { - console.log(' - upsert ' + account + ' / balance = ' + data[account].balance); - } else if (n == 6) { - console.log(' (...) total ' + accounts.length + ' accounts updated.'); - } - // upsert account - Account.collection.update({ address: account }, { $set: data[account] }, { upsert: true }); - }); - }); + } - if (bulk.length > 0) - Transaction.collection.insert(bulk, function( err, tx ){ - if ( typeof err !== 'undefined' && err ) { - if (err.code == 11000) { - if(!('quiet' in config && config.quiet === true)) { - console.log('Skip: Duplicate transaction key ' + err); + if (bulk.length > 0) { + Transaction.collection.insert(bulk, (err, tx) => { + if (typeof err !== 'undefined' && err) { + if (err.code == 11000) { + if (!('quiet' in config && config.quiet === true)) { + console.log(`Skip: Duplicate transaction key ${err}`); + } + } else { + console.log(`Error: Aborted due to error on Transaction: ${err}`); + process.exit(9); } } else { - console.log('Error: Aborted due to error on Transaction: ' + err); - process.exit(9); - } - } else { - if (!('quiet' in config && config.quiet === true)) { - console.log('* ' + tx.insertedCount + ' transactions successfully recorded.'); + if (!('quiet' in config && config.quiet === true)) { + console.log(`* ${tx.insertedCount} transactions successfully recorded.`); + } } - } - }); + }); + } } -} +}; /** //check oldest block or starting block then callback **/ const prepareSync = async (config, callback) => { - var blockNumber = null; - var oldBlockFind = Block.find({}, "number").lean(true).sort('number').limit(1); + let blockNumber = null; + const oldBlockFind = Block.find({}, 'number').lean(true).sort('number').limit(1); oldBlockFind.exec(async (err, docs) => { - if(err || !docs || docs.length < 1) { + if (err || !docs || docs.length < 1) { // not found in db. sync from config.endBlock or 'latest' - if(web3.eth.net.isListening()) { - var currentBlock = await web3.eth.getBlockNumber(); - var latestBlock = config.endBlock || currentBlock || 'latest'; - if(latestBlock === 'latest') { - web3.eth.getBlock(latestBlock, true, function(error, blockData) { - if(error) { - console.log('Warning (prepareSync): error on getting block with hash/number: ' + latestBlock + ': ' + error); - } else if(blockData == null) { - console.log('Warning: null block data received from the block with hash/number: ' + latestBlock); + if (web3.eth.net.isListening()) { + const currentBlock = await web3.eth.getBlockNumber(); + const latestBlock = config.endBlock || currentBlock || 'latest'; + if (latestBlock === 'latest') { + web3.eth.getBlock(latestBlock, true, (error, blockData) => { + if (error) { + console.log(`Warning (prepareSync): error on getting block with hash/number: ${latestBlock}: ${error}`); + } else if (blockData == null) { + console.log(`Warning: null block data received from the block with hash/number: ${latestBlock}`); } else { - console.log('Starting block number = ' + blockData.number); + console.log(`Starting block number = ${blockData.number}`); if ('quiet' in config && config.quiet === true) { - console.log("Quiet mode enabled"); + console.log('Quiet mode enabled'); } blockNumber = blockData.number - 1; callback(null, blockNumber); } }); } else { - console.log('Starting block number = ' + latestBlock); + console.log(`Starting block number = ${latestBlock}`); if ('quiet' in config && config.quiet === true) { - console.log("Quiet mode enabled"); + console.log('Quiet mode enabled'); } blockNumber = latestBlock - 1; callback(null, blockNumber); @@ -414,59 +439,59 @@ const prepareSync = async (config, callback) => { console.log('Error: Web3 connection error'); callback(err, null); } - }else{ + } else { blockNumber = docs[0].number - 1; - console.log('Old block found. Starting block number = ' + blockNumber); + console.log(`Old block found. Starting block number = ${blockNumber}`); if ('quiet' in config && config.quiet === true) { - console.log("Quiet mode enabled"); + console.log('Quiet mode enabled'); } callback(null, blockNumber); } }); -} +}; /** Block Patcher(experimental) **/ const runPatcher = async (config, startBlock, endBlock) => { - if(!web3 || !web3.eth.net.isListening()) { + if (!web3 || !web3.eth.net.isListening()) { console.log('Error: Web3 is not connected. Retrying connection shortly...'); - setTimeout(function() { runPatcher(config); }, 3000); + setTimeout(() => { runPatcher(config); }, 3000); return; } - if(typeof startBlock === 'undefined' || typeof endBlock === 'undefined') { + if (typeof startBlock === 'undefined' || typeof endBlock === 'undefined') { // get the last saved block - var blockFind = Block.find({}, "number").lean(true).sort('-number').limit(1); + const blockFind = Block.find({}, 'number').lean(true).sort('-number').limit(1); blockFind.exec(async (err, docs) => { - if(err || !docs || docs.length < 1) { + if (err || !docs || docs.length < 1) { // no blocks found. terminate runPatcher() console.log('No need to patch blocks.'); return; } - var lastMissingBlock = docs[0].number + 1; - var currentBlock = await web3.eth.getBlockNumber(); + const lastMissingBlock = docs[0].number + 1; + const currentBlock = await web3.eth.getBlockNumber(); runPatcher(config, lastMissingBlock, currentBlock - 1); }); return; } - var missingBlocks = endBlock - startBlock + 1; + const missingBlocks = endBlock - startBlock + 1; if (missingBlocks > 0) { - console.log('Patching from #' + startBlock + ' to #' + endBlock); - var patchBlock = startBlock; - var count = 0; - while(count < config.patchBlocks && patchBlock <= endBlock) { - if(!('quiet' in config && config.quiet === true)) { - console.log('Patching Block: ' + patchBlock) + console.log(`Patching from #${startBlock} to #${endBlock}`); + let patchBlock = startBlock; + let count = 0; + while (count < config.patchBlocks && patchBlock <= endBlock) { + if (!('quiet' in config && config.quiet === true)) { + console.log(`Patching Block: ${patchBlock}`); } - web3.eth.getBlock(patchBlock, true, function(error, patchData) { - if(error) { - console.log('Warning: error on getting block with hash/number: ' + patchBlock + ': ' + error); - } else if(patchData == null) { - console.log('Warning: null block data received from the block with hash/number: ' + patchBlock); + web3.eth.getBlock(patchBlock, true, (error, patchData) => { + if (error) { + console.log(`Warning: error on getting block with hash/number: ${patchBlock}: ${error}`); + } else if (patchData == null) { + console.log(`Warning: null block data received from the block with hash/number: ${patchBlock}`); } else { - checkBlockDBExistsThenWrite(config, patchData) + checkBlockDBExistsThenWrite(config, patchData); } }); patchBlock++; @@ -476,7 +501,7 @@ const runPatcher = async (config, startBlock, endBlock) => { writeBlockToDB(config, null, true); writeTransactionsToDB(config, null, true); - setTimeout(function() { runPatcher(config, patchBlock, endBlock); }, 1000); + setTimeout(() => { runPatcher(config, patchBlock, endBlock); }, 1000); } else { // flush writeBlockToDB(config, null, true); @@ -484,17 +509,17 @@ const runPatcher = async (config, startBlock, endBlock) => { console.log('*** Block Patching Completed ***'); } -} +}; /** This will be used for the patcher(experimental) **/ -var checkBlockDBExistsThenWrite = function(config, patchData, flush) { - Block.find({number: patchData.number}, function (err, b) { - if (!b.length){ +var checkBlockDBExistsThenWrite = function (config, patchData, flush) { + Block.find({ number: patchData.number }, (err, b) => { + if (!b.length) { writeBlockToDB(config, patchData, flush); writeTransactionsToDB(config, patchData, flush); } else if (!('quiet' in config && config.quiet === true)) { - console.log('Block number: ' +patchData.number.toString() + ' already exists in DB.'); + console.log(`Block number: ${patchData.number.toString()} already exists in DB.`); } }); }; @@ -505,35 +530,35 @@ var checkBlockDBExistsThenWrite = function(config, patchData, flush) { const quoteInterval = 10 * 60 * 1000; const getQuote = async () => { - const options = { - timeout: 10000 - } - const URL = `https://min-api.cryptocompare.com/data/price?fsym=${config.settings.symbol}&tsyms=USD`; + const options = { + timeout: 10000, + }; + const URL = `https://min-api.cryptocompare.com/data/price?fsym=${config.settings.symbol}&tsyms=USD`; - try { - let requestUSD = await fetch(URL); - let quoteUSD = await requestUSD.json(); + try { + const requestUSD = await fetch(URL); + const quoteUSD = await requestUSD.json(); - quoteObject = { - timestamp: Math.round( Date.now() / 1000), - quoteUSD: quoteUSD.USD, - } + quoteObject = { + timestamp: Math.round(Date.now() / 1000), + quoteUSD: quoteUSD.USD, + }; - new Market(quoteObject).save( ( err, market, count ) => { - if ( typeof err !== 'undefined' && err ) { - process.exit(9); - } else { - if(!('quiet' in config && config.quiet === true)) { - console.log('DB successfully written for market quote.'); - } - } - }); - } catch (error) { - if(!('quiet' in config && config.quiet === true)) { - console.log(error); + new Market(quoteObject).save((err, market, count) => { + if (typeof err !== 'undefined' && err) { + process.exit(9); + } else { + if (!('quiet' in config && config.quiet === true)) { + console.log('DB successfully written for market quote.'); + } } + }); + } catch (error) { + if (!('quiet' in config && config.quiet === true)) { + console.log(error); } -} + } +}; /** Start config for node connection and sync @@ -546,27 +571,27 @@ const getQuote = async () => { // load config.json var config = { nodeAddr: 'localhost', wsPort: 8546, bulkSize: 100 }; try { - var local = require('../config.json'); - _.extend(config, local); - console.log('config.json found.'); + 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); - } + 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); + } } -console.log('Connecting ' + config.nodeAddr + ':' + config.wsPort + '...'); +console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); // Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost -var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://' + config.nodeAddr + ':' + config.wsPort.toString())); +var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); // patch missing blocks -if (config.patch === true){ +if (config.patch === true) { console.log('Checking for missing blocks'); runPatcher(config); } @@ -581,14 +606,14 @@ if (process.env.NORICHLIST) { listenBlocks(config); // Starts full sync when set to true in config -if (config.syncAll === true){ +if (config.syncAll === true) { console.log('Starting Full Sync'); syncChain(config); } // Start price sync on DB -getQuote() +getQuote(); setInterval(() => { - getQuote() + getQuote(); }, quoteInterval); From 3b01745c026f882376e8cf18bd432ec850997bcc Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 09:21:25 +0900 Subject: [PATCH 30/46] cleanup: apply eslint settings to tools/sync.js --- tools/sync.js | 234 ++++++++++++++++++++++++-------------------------- 1 file changed, 112 insertions(+), 122 deletions(-) diff --git a/tools/sync.js b/tools/sync.js index 4606d3743..18dabf248 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -47,15 +47,35 @@ const ERC20ABI = [{ 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'from', 'type': 'address' }, { 'indexed': true, 'name': 'to', 'type': 'address' }, { 'indexed': false, 'name': 'value', 'type': 'uint256' }], 'name': 'Transfer', 'type': 'event', }]; const ERC20_METHOD_DIC = { '0xa9059cbb': 'transfer', '0xa978501e': 'transferFrom' }; -const METHOD_DIC = { - '0x930a61a57a70a73c2a503615b87e2e54fe5b9cdeacda518270b852296ab1a377': 'Transfer(address,address,uint)', - '0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b': 'transfer(address,uint256)', - '0xa978501e4506ecbd340f6e45a48ac5bd126b1c14f03f2210837c8e0b602d4d7b': 'transferFrom(address,address,uint)', - '0x086c40f692cc9c13988b9e49a7610f67375e8373bfe7653911770b351c2b1c54': 'approve(address,uint)', - '0xf2fde38b092330466c661fc723d5289b90272a3e580e3187d1d7ef788506c557': 'transferOwnership(address)', - '0x3bc50cfd0fe2c05fb67c0fe4be91fb10eb723ba30ea8f559d533fcd5fe29be7f': 'Released(address,uint)', - '0xb21fb52d5749b80f3182f8c6992236b5e5576681880914484d7f4c9b062e619e': 'Released(address indexed, uint indexed)', -}; + +/** + Start config for node connection and sync +**/ +/** + * nodeAddr: node address + * wsPort: rpc port + * bulkSize: size of array in block to use bulk operation + */ +// load config.json +var config = { nodeAddr: 'localhost', wsPort: 8546, 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); + } +} + +console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); +// Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost +var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); const normalizeTX = async (txData, receipt, blockData) => { const tx = { @@ -93,78 +113,6 @@ const normalizeTX = async (txData, receipt, blockData) => { }; -/** - //Just listen for latest blocks and sync from the start of the app. -**/ -const listenBlocks = function (config) { - const newBlocks = web3.eth.subscribe('newBlockHeaders', (error, result) => { - if (!error) { - return; - } - - console.error(error); - }); - newBlocks.on('data', (blockHeader) => { - web3.eth.getBlock(blockHeader.hash, true, (error, blockData) => { - if (blockHeader == null) { - console.log('Warning: null block hash'); - } else { - writeBlockToDB(config, blockData, true); - writeTransactionsToDB(config, blockData, true); - } - }); - }); - newBlocks.on('error', console.error); -}; -/** - If full sync is checked this function will start syncing the block chain from lastSynced param see README -**/ -var syncChain = function (config, nextBlock) { - if (web3.eth.net.isListening()) { - if (typeof nextBlock === 'undefined') { - prepareSync(config, (error, startBlock) => { - if (error) { - console.log(`ERROR: error: ${error}`); - return; - } - syncChain(config, startBlock); - }); - return; - } - - if (nextBlock == null) { - console.log('nextBlock is null'); - return; - } if (nextBlock < config.startBlock) { - writeBlockToDB(config, null, true); - writeTransactionsToDB(config, null, true); - console.log('*** Sync Finsihed ***'); - config.syncAll = false; - return; - } - - let count = config.bulkSize; - while (nextBlock >= config.startBlock && count > 0) { - web3.eth.getBlock(nextBlock, true, (error, blockData) => { - if (error) { - console.log(`Warning (syncChain): error on getting block with hash/number: ${nextBlock}: ${error}`); - } else if (blockData == null) { - console.log(`Warning: null block data received from the block with hash/number: ${nextBlock}`); - } else { - writeBlockToDB(config, blockData); - writeTransactionsToDB(config, blockData); - } - }); - nextBlock--; - count--; - } - - setTimeout(() => { syncChain(config, nextBlock); }, 500); - } else { - console.log(`Error: Web3 connection time out trying to get block ${nextBlock} retrying connection now`); - syncChain(config, nextBlock); - } -}; /** Write the whole block object to DB **/ @@ -183,11 +131,11 @@ var writeBlockToDB = function (config, blockData, flush) { if (flush && self.bulkOps.length > 0 || self.bulkOps.length >= config.bulkSize) { const bulk = self.bulkOps; self.bulkOps = []; - if (bulk.length == 0) return; + if (bulk.length === 0) return; Block.collection.insert(bulk, (err, blocks) => { if (typeof err !== 'undefined' && err) { - if (err.code == 11000) { + if (err.code === 11000) { if (!('quiet' in config && config.quiet === true)) { console.log(`Skip: Duplicate DB key : ${err}`); } @@ -227,7 +175,7 @@ const writeTransactionsToDB = async (config, blockData, flush) => { // Contact creation tx, Event logs of internal transaction if (txData.input && txData.input.length > 2) { // Contact creation tx - if (txData.to == null) { + if (txData.to === null) { contractAddress = txData.creates.toLowerCase(); const contractdb = {}; let isTokenContract = true; @@ -237,7 +185,7 @@ const writeTransactionsToDB = async (config, blockData, flush) => { contractdb.creationTransaction = txData.hash; try { const call = await web3.eth.call({ to: contractAddress, data: web3.utils.sha3('totalSupply()') }); - if (call == '0x') { + if (call === '0x') { isTokenContract = false; } else { try { @@ -276,8 +224,8 @@ const writeTransactionsToDB = async (config, blockData, flush) => { 'hash': '', 'blockNumber': 0, 'from': '', 'to': '', 'contract': '', 'value': 0, 'timestamp': 0, }; const methodCode = txData.input.substr(0, 10); - if (ERC20_METHOD_DIC[methodCode] == 'transfer' || ERC20_METHOD_DIC[methodCode] == 'transferFrom') { - if (ERC20_METHOD_DIC[methodCode] == 'transfer') { + if (ERC20_METHOD_DIC[methodCode] === 'transfer' || ERC20_METHOD_DIC[methodCode] === 'transferFrom') { + if (ERC20_METHOD_DIC[methodCode] === 'transfer') { // Token transfer transaction transfer.from = txData.from; transfer.to = `0x${txData.input.substring(34, 74)}`; @@ -338,7 +286,7 @@ const writeTransactionsToDB = async (config, blockData, flush) => { const accounts = Object.keys(data); - if (bulk.length == 0 && accounts.length == 0) return; + if (bulk.length === 0 && accounts.length === 0) return; // update balances if (config.useRichList && accounts.length > 0) { @@ -371,7 +319,7 @@ const writeTransactionsToDB = async (config, blockData, flush) => { n++; if (n <= 5) { console.log(` - upsert ${account} / balance = ${data[account].balance}`); - } else if (n == 6) { + } else if (n === 6) { console.log(` (...) total ${accounts.length} accounts updated.`); } // upsert account @@ -383,7 +331,7 @@ const writeTransactionsToDB = async (config, blockData, flush) => { if (bulk.length > 0) { Transaction.collection.insert(bulk, (err, tx) => { if (typeof err !== 'undefined' && err) { - if (err.code == 11000) { + if (err.code === 11000) { if (!('quiet' in config && config.quiet === true)) { console.log(`Skip: Duplicate transaction key ${err}`); } @@ -400,6 +348,78 @@ const writeTransactionsToDB = async (config, blockData, flush) => { } } }; +/** + //Just listen for latest blocks and sync from the start of the app. +**/ +const listenBlocks = function (config) { + const newBlocks = web3.eth.subscribe('newBlockHeaders', (error, result) => { + if (!error) { + return; + } + + console.error(error); + }); + newBlocks.on('data', (blockHeader) => { + web3.eth.getBlock(blockHeader.hash, true, (error, blockData) => { + if (blockHeader === null) { + console.log('Warning: null block hash'); + } else { + writeBlockToDB(config, blockData, true); + writeTransactionsToDB(config, blockData, true); + } + }); + }); + newBlocks.on('error', console.error); +}; +/** + If full sync is checked this function will start syncing the block chain from lastSynced param see README +**/ +var syncChain = function (config, nextBlock) { + if (web3.eth.net.isListening()) { + if (typeof nextBlock === 'undefined') { + prepareSync(config, (error, startBlock) => { + if (error) { + console.log(`ERROR: error: ${error}`); + return; + } + syncChain(config, startBlock); + }); + return; + } + + if (nextBlock === null) { + console.log('nextBlock is null'); + return; + } if (nextBlock < config.startBlock) { + writeBlockToDB(config, null, true); + writeTransactionsToDB(config, null, true); + console.log('*** Sync Finsihed ***'); + config.syncAll = false; + return; + } + + let count = config.bulkSize; + while (nextBlock >= config.startBlock && count > 0) { + web3.eth.getBlock(nextBlock, true, (error, blockData) => { + if (error) { + console.log(`Warning (syncChain): error on getting block with hash/number: ${nextBlock}: ${error}`); + } else if (blockData === null) { + console.log(`Warning: null block data received from the block with hash/number: ${nextBlock}`); + } else { + writeBlockToDB(config, blockData); + writeTransactionsToDB(config, blockData); + } + }); + nextBlock--; + count--; + } + + setTimeout(() => { syncChain(config, nextBlock); }, 500); + } else { + console.log(`Error: Web3 connection time out trying to get block ${nextBlock} retrying connection now`); + syncChain(config, nextBlock); + } +}; /** //check oldest block or starting block then callback **/ @@ -416,7 +436,7 @@ const prepareSync = async (config, callback) => { web3.eth.getBlock(latestBlock, true, (error, blockData) => { if (error) { console.log(`Warning (prepareSync): error on getting block with hash/number: ${latestBlock}: ${error}`); - } else if (blockData == null) { + } else if (blockData === null) { console.log(`Warning: null block data received from the block with hash/number: ${latestBlock}`); } else { console.log(`Starting block number = ${blockData.number}`); @@ -488,7 +508,7 @@ const runPatcher = async (config, startBlock, endBlock) => { web3.eth.getBlock(patchBlock, true, (error, patchData) => { if (error) { console.log(`Warning: error on getting block with hash/number: ${patchBlock}: ${error}`); - } else if (patchData == null) { + } else if (patchData === null) { console.log(`Warning: null block data received from the block with hash/number: ${patchBlock}`); } else { checkBlockDBExistsThenWrite(config, patchData); @@ -560,36 +580,6 @@ const getQuote = async () => { } }; -/** - Start config for node connection and sync -**/ -/** - * nodeAddr: node address - * wsPort: rpc port - * bulkSize: size of array in block to use bulk operation - */ -// load config.json -var config = { nodeAddr: 'localhost', wsPort: 8546, 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); - } -} - -console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); - -// Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost -var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); - // patch missing blocks if (config.patch === true) { console.log('Checking for missing blocks'); From 7b15be4e5e4fbd097f25b0b7aac07b745102ee11 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 09:29:22 +0900 Subject: [PATCH 31/46] cleanup: apply eslint settings to richlist.js & stats.js --- tools/richlist.js | 38 +++++++++++++++++++------------------- tools/stats.js | 42 +++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/tools/richlist.js b/tools/richlist.js index ec63e9d4e..a95dba19b 100644 --- a/tools/richlist.js +++ b/tools/richlist.js @@ -16,6 +16,25 @@ const { Block } = require('../db.js'); const ADDRESS_CACHE_MAX = 10000; // address cache threshold +/** + * Start config for node connection and sync + */ +var config = { nodeAddr: 'localhost', 'wsPort': 8546 }; +// load the config.json file +try { + const loaded = require('../config.json'); + _.extend(config, loaded); + console.log('config.json found.'); +} catch (error) { + console.log('No config file found.'); + throw error; + process.exit(1); +} + +console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); +// Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost +var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); + // RichList for Geth Classic, Geth function makeRichList(toBlock, blocks, updateCallback) { const self = makeRichList; @@ -417,29 +436,10 @@ function readJsonAccounts(json, blockNumber, callback, defaultType = 0) { }); } -/** - * Start config for node connection and sync - */ -var config = { nodeAddr: 'localhost', 'wsPort': 8546 }; -// load the config.json file -try { - const loaded = require('../config.json'); - _.extend(config, loaded); - console.log('config.json found.'); -} catch (error) { - console.log('No config file found.'); - throw error; - process.exit(1); -} - // temporary turn on some debug //config.quiet = false; //mongoose.set('debug', true); -console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); - -var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); - async function startSync() { const latestBlock = await web3.eth.getBlockNumber(); const nodeInfo = await web3.eth.getNodeInfo(); diff --git a/tools/stats.js b/tools/stats.js index 56f928eff..c720175ce 100644 --- a/tools/stats.js +++ b/tools/stats.js @@ -8,6 +8,27 @@ const Web3 = require('web3'); const mongoose = require('mongoose'); const { BlockStat } = require('../db.js'); +// load config.json +const config = { nodeAddr: 'localhost', wsPort: 8546, 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); + } +} + +console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); +// Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost +var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); + const updateStats = async (range, interval, rescan) => { let latestBlock = await web3.eth.getBlockNumber(); @@ -133,27 +154,6 @@ if (process.env.RESCAN) { rescan = true; } -// load config.json -const config = { nodeAddr: 'localhost', wsPort: 8546, 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); - } -} - -console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); - -var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); - // run updateStats(range, interval, rescan); From f3b5c3c636bd74627c2c6e88e41c76f9fdde0ffb Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 09:30:38 +0900 Subject: [PATCH 32/46] cleanup: more cleanup for tools --- tools/richlist.js | 4 ++-- tools/stats.js | 2 +- tools/sync.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/richlist.js b/tools/richlist.js index a95dba19b..9283aa0dc 100644 --- a/tools/richlist.js +++ b/tools/richlist.js @@ -19,7 +19,7 @@ const ADDRESS_CACHE_MAX = 10000; // address cache threshold /** * Start config for node connection and sync */ -var config = { nodeAddr: 'localhost', 'wsPort': 8546 }; +const config = { nodeAddr: 'localhost', 'wsPort': 8546 }; // load the config.json file try { const loaded = require('../config.json'); @@ -33,7 +33,7 @@ try { console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); // Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost -var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); +const web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); // RichList for Geth Classic, Geth function makeRichList(toBlock, blocks, updateCallback) { diff --git a/tools/stats.js b/tools/stats.js index c720175ce..e746cc9e9 100644 --- a/tools/stats.js +++ b/tools/stats.js @@ -27,7 +27,7 @@ try { console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); // Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost -var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); +const web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); const updateStats = async (range, interval, rescan) => { let latestBlock = await web3.eth.getBlockNumber(); diff --git a/tools/sync.js b/tools/sync.js index 18dabf248..1f52b7cc2 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -57,7 +57,7 @@ const ERC20_METHOD_DIC = { '0xa9059cbb': 'transfer', '0xa978501e': 'transferFrom * bulkSize: size of array in block to use bulk operation */ // load config.json -var config = { nodeAddr: 'localhost', wsPort: 8546, bulkSize: 100 }; +const config = { nodeAddr: 'localhost', wsPort: 8546, bulkSize: 100 }; try { var local = require('../config.json'); _.extend(config, local); @@ -75,7 +75,7 @@ try { console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); // Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost -var web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); +const web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); const normalizeTX = async (txData, receipt, blockData) => { const tx = { From bf4dd534aa57a365513e040889c9778bd923a9d5 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 09:46:47 +0900 Subject: [PATCH 33/46] cleanup: update .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index b7e28db57..14dc2ca81 100644 --- a/.gitignore +++ b/.gitignore @@ -38,7 +38,6 @@ jspm_packages # local data data/ -package-lock.json config.json .node-xmlhttprequest-* /nbproject/private/ From ebfd99670b9ea95e3f3a05e8a5406373c812dafc Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 09:59:25 +0900 Subject: [PATCH 34/46] enhancement: support travis build for eslint check --- .travis.yml | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index c28c225ad..fbb5cafa8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,32 @@ language: node_js sudo: required -dist: trusty -node_js: '8' -env: CXX=g++-4.8 -services: - - docker -before_install: - - docker pull trufflesuite/ganache-cli - - docker run -d -p 8546:8546 -p 27017:27017 trufflesuite/ganache-cli -p 8546 - - varA=`docker ps --no-trunc -q | cut -c 1-12` - - docker pull mongo - - docker run -d --network="container:$varA" mongo - - docker build -t ethereumclassic/explorer . - - docker run -d --network="container:$varA" ethereumclassic/explorer app.js -script: -- npm run test +matrix: + include: + # This builder checks explorer build + - os: linux + dist: xenial + node_js: '8' + services: + - docker + before_install: + - docker pull trufflesuite/ganache-cli + - docker run -d -p 8546:8546 -p 27017:27017 trufflesuite/ganache-cli -p 8546 + - varA=`docker ps --no-trunc -q | cut -c 1-12` + - docker pull mongo + - docker run -d --network="container:$varA" mongo + - docker build -t ethereumclassic/explorer . + - docker run -d --network="container:$varA" ethereumclassic/explorer app.js + script: + - npm run test + + # This builder only tests code linters + - os: linux + dist: xenial + node_js: '8' + env: lint + script: + - npm run lint:check + + # Temporary allow failures for eslint until the code is done. + allow_failures: + - env: lint From e7bac341a36b4ab02317a73db482e44b072d7dd3 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 16:45:03 +0900 Subject: [PATCH 35/46] cleanup: add html linter --- html-linter.json | 16 ++++++++++++++++ package-lock.json | 19 +++++++++++++++++++ package.json | 3 ++- 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 html-linter.json diff --git a/html-linter.json b/html-linter.json new file mode 100644 index 000000000..cca545c29 --- /dev/null +++ b/html-linter.json @@ -0,0 +1,16 @@ +{ + "files": [ + "./public/tpl/*.html", + "./public/views/*.html", + "public/views/stats/*.html" + ], + "indentation": { + "char": "space", + "number": 2 + }, + "attributes": { + "quotes": "double", + "whitespace": 0, + "vertical-align": true + } +} diff --git a/package-lock.json b/package-lock.json index bb4c2475e..784aa7bc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2294,6 +2294,25 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" }, + "html-linter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/html-linter/-/html-linter-1.1.1.tgz", + "integrity": "sha512-DJfLevdq+YmY4R7yMdD0zaCAJOvWihg+eCe5o/jeTw86grvgmvSCIwBv1mDi+UdeJP9mDoi5rB6KtcFOn8StrA==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "commander": "^2.12.2", + "glob": "^7.1.2" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + } + } + }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", diff --git a/package.json b/package.json index 8e68d0902..a64c9dba1 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "stats": "node tools/stats.js", "rich": "node tools/richlist.js", "test": "mocha --exit", - "lint:check": "eslint *.js ./lib/*.js ./routes/*.js ./tools/*.js", + "lint:check": "concurrently \"eslint *.js ./lib/*.js ./routes/*.js ./tools/*.js \" \"html-linter --config html-linter.json\" ", "lint:fix": "eslint *.js ./lib/*.js ./routes/*.js ./tools/*.js --fix" }, "dependencies": { @@ -34,6 +34,7 @@ "eslint": "^5.15.3", "eslint-config-airbnb-base": "^13.1.0", "eslint-plugin-import": "^2.16.0", + "html-linter": "^1.1.1", "mocha": "^6.0.2", "request": "^2.88.0" } From 3671e3dfbe3b971e47c5e31764712504881758e3 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 17:01:42 +0900 Subject: [PATCH 36/46] cleanup: format html files * follow 2 spaces rules that is described on html-formatter --- html-linter.json | 2 +- public/tpl/footer.html | 80 ++++---- public/tpl/header.html | 245 ++++++++++++------------- public/tpl/page-head.html | 18 +- public/views/address.html | 199 ++++++++++---------- public/views/block.html | 90 +++++---- public/views/contract-source.html | 24 +-- public/views/contract.html | 233 +++++++++++------------ public/views/created-tokens.html | 63 ++++--- public/views/err_404.html | 23 +-- public/views/home.html | 130 +++++++------ public/views/simple-summary-stats.html | 106 +++++------ public/views/site-notes.html | 8 +- public/views/stats/index.html | 20 +- public/views/token.html | 212 ++++++++++----------- public/views/tokenlist.html | 21 +-- public/views/transfer-tokens.html | 67 ++++--- public/views/tx.html | 154 ++++++++++------ 18 files changed, 863 insertions(+), 832 deletions(-) diff --git a/html-linter.json b/html-linter.json index cca545c29..bc560efb3 100644 --- a/html-linter.json +++ b/html-linter.json @@ -2,7 +2,7 @@ "files": [ "./public/tpl/*.html", "./public/views/*.html", - "public/views/stats/*.html" + "./public/views/stats/*.html" ], "indentation": { "char": "space", diff --git a/public/tpl/footer.html b/public/tpl/footer.html index 0ca2be55c..42380fdd6 100755 --- a/public/tpl/footer.html +++ b/public/tpl/footer.html @@ -1,51 +1,51 @@
    -
    -
    - - - -
    +
    +
    + + +
    +
    - +
    diff --git a/public/tpl/header.html b/public/tpl/header.html index 27b3afb88..815953d73 100755 --- a/public/tpl/header.html +++ b/public/tpl/header.html @@ -1,139 +1,136 @@
    diff --git a/public/tpl/page-head.html b/public/tpl/page-head.html index 03f0a6d4e..0a2355423 100755 --- a/public/tpl/page-head.html +++ b/public/tpl/page-head.html @@ -1,10 +1,10 @@
    - -
    -

    - - -

    -
    - -
    \ No newline at end of file + +
    +

    + + +

    +
    + + diff --git a/public/views/address.html b/public/views/address.html index af6adbcd9..8bc099868 100644 --- a/public/views/address.html +++ b/public/views/address.html @@ -1,109 +1,112 @@
    -
    -
    Contract Overview
    -
    -
    -
    -
    -
    - - {{ addr.balance | number: 4 }} {{ settings.symbol }}
    - - {{ settings.symbol }} Balance -
    -
    - {{ addr.balanceUSD | currency : "$" : 4 }} USD balance -
    -
    - {{ addr.mined }} Mined -
    -
    - {{ addr.count }} Transactions -
    -
    +
    +
    Contract Overview
    +
    +
    +
    +
    +
    + + {{ addr.balance | number: 4 }} {{ settings.symbol }}
    + + {{ settings.symbol }} Balance +
    +
    + {{ addr.balanceUSD | currency : "$" : 4 }} USD balance +
    +
    + {{ addr.mined }} Mined
    -
    - -
    - Token Address
    - {{addr.address}} -
    +
    + {{ addr.count }} Transactions
    -
    -
    -
    - +
    +
    +
    + +
    + Token Address
    + {{addr.address}} +
    +
    +
    + +
    + +
    +
    height<Prev {{block.number | number}} Next>
    Time{{block.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }} ({{block.timestamp | timeDuration}} ago)
    Block Height<Prev {{block.number | number}} Next>
    TimeStamp{{block.timestamp | timeDuration}} ago ({{block.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }})
    Hash{{block.hash}}
    parentHash{{block.parentHash}}
    sha3 Uncles{{block.sha3Uncles}}
    Mined By{{block.miner}}
    Parent Hash{{block.parentHash}}
    Sha3Uncles{{block.sha3Uncles}}
    Mined by{{block.miner}}
    Difficulty{{block.difficulty | totalDifficulty}}
    Total Difficulty{{block.totalDifficulty | totalDifficulty}}
    Gas Limit{{block.gasLimit | number}}
    Gas Used{{block.gasUsed | number}}
    nonce{{block.nonce}}
    Extra Data{{block.extraData}}
    Nonce{{block.nonce}}
    Extra Data{{block.extraData}} (Hex: {{block.extraDataHex}})
    Uncles{{block.uncles.length}} uncles diff --git a/public/views/tx.html b/public/views/tx.html index 9462e9007..33fd8cb19 100644 --- a/public/views/tx.html +++ b/public/views/tx.html @@ -4,24 +4,41 @@
    - - - - + + + + + + + + - - + + + + + + + + + + + + + + + - - - - - - - - - - +
    hash{{tx.hash}}
    blockNumber{{tx.blockNumber}}
    Transaction Hash:{{tx.hash}}
    Status: + Failed (Error encountered during transaction !) + Success + Pending + Not exist +
    Block: + {{tx.blockNumber | number}} + + +
    TimeStamp: {{tx.timestamp | timeDuration}} ago ({{tx.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }})
    Time{{tx.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }} ({{tx.timestamp | timeDuration}} ago)
    From:{{tx.from}}
    To:{{tx.to}}
    Creates:{{tx.creates}}
    Value:{{tx.value | number: 8}} {{ settings.symbol }}
    Transaction fee:{{tx.txFee | number : 6}} {{ settings.symbol }}
    Gas Limit:{{tx.gas | number}}
    Gas Used by Transaction:{{tx.gasUsed | number}}
    Gas Price:{{tx.gasPriceEther | number:9}} {{ settings.symbol }} ({{tx.gasPriceGwei | number}} Gwei)
    from{{tx.from}}
    to{{tx.to}}
    creates{{tx.creates}}
    value{{tx.value}} {{ settings.symbol }}
    gas Provided{{tx.gas | number}}
    gasPrice{{tx.gasPrice | number}}
    nonce{{tx.nonce}}
    Nonce:{{tx.nonce}}
    Input Data
    {{tx.input}}
    diff --git a/routes/web3relay.js b/routes/web3relay.js index 6d8a46b9b..a34496874 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -11,6 +11,11 @@ var _ = require('lodash'); var BigNumber = require('bignumber.js'); var etherUnits = require(__lib + "etherUnits.js") +require( '../db.js' ); +var mongoose = require( 'mongoose' ); +var Block = mongoose.model( 'Block' ); +var Transaction = mongoose.model( 'Transaction' ); + var getLatestBlocks = require('./index').getLatestBlocks; var filterBlocks = require('./filters').filterBlocks; var filterTrace = require('./filters').filterTrace; @@ -60,36 +65,65 @@ exports.data = function(req, res){ if ("tx" in req.body) { var txHash = req.body.tx.toLowerCase(); - web3.eth.getTransaction(txHash, function(err, tx) { - if(err || !tx) { - console.error("TxWeb3 error :" + err) - if (!tx) { - web3.eth.getBlock(txHash, function(err, block) { - if(err || !block) { - console.error("BlockWeb3 error :" + err) - res.write(JSON.stringify({"error": true})); + Transaction.findOne({hash: txHash}).lean(true).exec(function(err, doc) { + if (err || !doc) { + web3.eth.getTransaction(txHash, function(err, tx) { + if(err || !tx) { + console.error("TxWeb3 error :" + err) + if (!tx) { + web3.eth.getBlock(txHash, function(err, block) { + if(err || !block) { + console.error("BlockWeb3 error :" + err) + res.write(JSON.stringify({"error": true})); + } else { + console.log("BlockWeb3 found: " + txHash) + res.write(JSON.stringify({"error": true, "isBlock": true})); + } + res.end(); + }); } else { - console.log("BlockWeb3 found: " + txHash) - res.write(JSON.stringify({"error": true, "isBlock": true})); + res.write(JSON.stringify({"error": true})); + res.end(); } - res.end(); - }); - } else { - res.write(JSON.stringify({"error": true})); - res.end(); - } - } else { - var ttx = tx; - ttx.value = etherUnits.toEther( new BigNumber(tx.value), "wei"); - //get timestamp from block - var block = web3.eth.getBlock(tx.blockNumber, function(err, block) { - if (!err && block) - ttx.timestamp = block.timestamp; - ttx.isTrace = (ttx.input != "0x"); - res.write(JSON.stringify(ttx)); - res.end(); + } else { + var ttx = tx; + ttx.value = etherUnits.toEther( new BigNumber(tx.value), "wei"); + //get TxReceipt status & gasUsed + web3.eth.getTransactionReceipt(txHash, function(err, receipt) { + if (err) { + console.error(err); + return; + } + if(receipt.status != null) + ttx.status = receipt.status; + ttx.gasUsed = receipt.gasUsed; + }); + //get timestamp from block + var block = web3.eth.getBlock(tx.blockNumber, function(err, block) { + if (!err && block) + ttx.timestamp = block.timestamp; + ttx.isTrace = (ttx.input != "0x"); + txResponse = ttx; + }); + } }); + } else { + txResponse = doc; + } + + var latestBlock = web3.eth.blockNumber + 1; + + txResponse.confirmations = latestBlock - txResponse.blockNumber; + + if (txResponse.confirmations === latestBlock) { + txResponse.confirmation = 0; } + txResponse.gasPriceGwei = etherUnits.toGwei( new BigNumber(txResponse.gasPrice), "wei"); + txResponse.gasPriceEther = etherUnits.toEther( new BigNumber(txResponse.gasPrice), "wei"); + txResponse.txFee = txResponse.gasPriceEther * txResponse.gasUsed; + + res.write(JSON.stringify(txResponse)); + res.end(); }); } else if ("tx_trace" in req.body) { @@ -158,8 +192,6 @@ exports.data = function(req, res){ res.write(JSON.stringify(addrData)); res.end(); - - } else if ("block" in req.body) { var blockNumOrHash; if (/^(0x)?[0-9a-f]{64}$/i.test(req.body.block.trim())) { @@ -168,14 +200,25 @@ exports.data = function(req, res){ blockNumOrHash = parseInt(req.body.block); } - web3.eth.getBlock(blockNumOrHash, function(err, block) { - if(err || !block) { - console.error("BlockWeb3 error :" + err) - res.write(JSON.stringify({"error": true})); - } else { - res.write(JSON.stringify(filterBlocks(block))); - } - res.end(); + Block.findOne({$or: [{hash: blockNumOrHash}, {number: blockNumOrHash}]}, + { '_id': 0 }).lean(true).exec("findOne", function(err, doc) { + if (err || !doc) { + web3.eth.getBlock(blockNumOrHash, function(err, block) { + if(err || !block) { + console.error("BlockWeb3 error :" + err) + res.write(JSON.stringify({"error": true})); + } else { + res.write(JSON.stringify(filterBlocks(block))); + } + res.end(); + }); + } else { + Transaction.find({blockNumber: doc.number}).distinct("hash", (err, txs) => { + doc["transactions"] = txs; + res.write(JSON.stringify(filterBlocks(doc))); + res.end(); + }); + } }); /* @@ -202,7 +245,7 @@ exports.data = function(req, res){ return; } - web3.eth.getUncle(blockNumOrHash, uncleIdx, function(err, uncle) { + web3.eth.getBlock(blockNumOrHash, uncleIdx, function(err, uncle) { if(err || !uncle) { console.error("UncleWeb3 error :" + err) res.write(JSON.stringify({"error": true})); diff --git a/tools/patcher.js b/tools/patcher.js index ce41a6014..d00f039fb 100644 --- a/tools/patcher.js +++ b/tools/patcher.js @@ -8,6 +8,52 @@ var mongoose = require( 'mongoose' ); var Block = mongoose.model( 'Block' ); var Transaction = mongoose.model( 'Transaction' ); +function normalizeTX(txData, blockData) { + var tx = { + blockHash: txData.blockHash, + blockNumber: txData.blockNumber, + from: txData.from.toLowerCase(), + hash: txData.hash.toLowerCase(), + value: etherUnits.toEther(new BigNumber(txData.value), 'wei'), + nonce: txData.nonce, + r: txData.r, + s: txData.s, + v: txData.v, + gas: txData.gas, + gasPrice: String(txData.gasPrice), + input: txData.input, + transactionIndex: txData.transactionIndex, + timestamp: blockData.timestamp + }; + // getTransactionReceipt to get contract address and more data + + var receipt; + try { + receipt = web3.eth.getTransactionReceipt(txData.hash) + } catch(err) { + console.log('Error', err); + } + tx.gasUsed = receipt.gasUsed; + + if (receipt.status) + tx.status = receipt.status; + + if (txData.to) { + tx.to = txData.to.toLowerCase(); + return tx; + } else { + if (tx.creates) { + tx.creates = txData.creates.toLowerCase(); + return tx; + } else { + if (receipt && receipt.contractAddress) { + tx.creates = receipt.contractAddress; + } + return tx; + } + } +} + var grabBlock = function(config, web3, blockHashOrNumber) { var desiredBlockHashOrNumber; // check if done @@ -81,9 +127,9 @@ var writeTransactionsToDB = function(config, blockData) { if (blockData.transactions.length > 0) { for (d in blockData.transactions) { var txData = blockData.transactions[d]; - txData.timestamp = blockData.timestamp; - txData.value = etherUnits.toEther(new BigNumber(txData.value), 'wei'); - bulkOps.push(txData); + + var tx = normalizeTX(txData, blockData); + bulkOps.push(tx); } Transaction.collection.insert(bulkOps, function( err, tx ){ if ( typeof err !== 'undefined' && err ) { diff --git a/tools/sync.js b/tools/sync.js index f2e121416..f93f200ff 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -17,6 +17,52 @@ var Block = mongoose.model( 'Block' ); var Transaction = mongoose.model( 'Transaction' ); var Account = mongoose.model( 'Account' ); +function normalizeTX(txData, blockData) { + var tx = { + blockHash: txData.blockHash, + blockNumber: txData.blockNumber, + from: txData.from.toLowerCase(), + hash: txData.hash.toLowerCase(), + value: etherUnits.toEther(new BigNumber(txData.value), 'wei'), + nonce: txData.nonce, + r: txData.r, + s: txData.s, + v: txData.v, + gas: txData.gas, + gasPrice: String(txData.gasPrice), + input: txData.input, + transactionIndex: txData.transactionIndex, + timestamp: blockData.timestamp + }; + // getTransactionReceipt to get contract address and more data + + var receipt; + try { + receipt = web3.eth.getTransactionReceipt(txData.hash) + } catch(err) { + console.log('Error', err); + } + tx.gasUsed = receipt.gasUsed; + + if (receipt.status) + tx.status = receipt.status; + + if (txData.to) { + tx.to = txData.to.toLowerCase(); + return tx; + } else { + if (tx.creates) { + tx.creates = txData.creates.toLowerCase(); + return tx; + } else { + if (receipt && receipt.contractAddress) { + tx.creates = receipt.contractAddress; + } + return tx; + } + } +} + /** //Just listen for latest blocks and sync from the start of the app. **/ @@ -163,9 +209,9 @@ var writeTransactionsToDB = function(config, blockData, flush) { if (blockData && blockData.transactions.length > 0) { for (d in blockData.transactions) { var txData = blockData.transactions[d]; - txData.timestamp = blockData.timestamp; - txData.value = etherUnits.toEther(new BigNumber(txData.value), 'wei'); - self.bulkOps.push(txData); + + var tx = normalizeTX(txData, blockData); + self.bulkOps.push(tx); } console.log('\t- block #' + blockData.number.toString() + ': ' + blockData.transactions.length.toString() + ' transactions recorded.'); } From dc55f99f0f917d9944b23a979cb29c1a44b77f0c Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Wed, 20 Mar 2019 02:44:26 +0900 Subject: [PATCH 19/46] enhancement: add fiat exchange for addresses and tx cherry picked from EthereumCommonwealth/clo-explorer@c4502a0 by @yograteol * configurable fiat conversion * hide fiat value when it is not used. * use cryptocompare instead of coinmarketcap --- README.md | 42 ++--- config.example.json | 1 + db.js | 11 ++ package.json | 6 + public/css/custom.css | 3 + public/img/etc-mini-logo.svg | 289 +++++++++++++++++++++++++++++++++++ public/views/address.html | 16 +- public/views/tx.html | 4 +- routes/web3relay.js | 24 ++- tools/price.js | 60 ++++++++ 10 files changed, 421 insertions(+), 35 deletions(-) create mode 100644 public/img/etc-mini-logo.svg create mode 100644 tools/price.js diff --git a/README.md b/README.md index d1b032eca..d223affda 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Basic settings: "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, + "useFiat": false, "miners": { "0xdf7d7e053933b5cc24372f878c90e62dadad5d42": "EtherMine", "0xc91716199ccde49dc4fafaeb68925127ac80443f": "F2Pool", @@ -91,23 +92,17 @@ Basic settings: ``` -```nodeAddr``` Your node API RPC address. - -```rpcPort``` Your node API RPC port. - -```startBlock``` This is the start block of the blockchain, should always be 0 if you want to sync the whole ETC blockchain. - -```endBlock``` This is usually the 'latest'/'newest' block in the blockchain, this value gets updated automatically, and will be used to patch missing blocks if the whole app goes down. - -```quiet``` Suppress some messages. (admittedly still not quiet) - -```syncAll``` If this is set to true at the start of the app, the sync will start syncing all blocks from lastSync, and if lastSync is 0 it will start from whatever the endBlock or latest block in the blockchain is. - -```patch``` If set to true and below value is set, sync will iterated through the # of blocks specified. - -```patchBlocks``` If `patch` is set to true, the amount of block specified will be check from the latest one. - -```useRichList``` If `useRichList` is set to true, explorer will update account balance for richlist page. +| Name | Explanation | +|-------------|-----| +| `nodeAddr` | Your node API RPC address. | +| `wsPort` | Your node API WS (Websocket) port. (RPC HTTP port is deprecated on Web3 1.0 see https://web3js.readthedocs.io/en/1.0/web3.html#value) | +| `startBlock` | This is the start block of the blockchain, should always be 0 if you want to sync the whole ETC blockchain. | +| `endBlock` | This is usually the 'latest'/'newest' block in the blockchain, this value gets updated automatically, and will be used to patch missing blocks if the whole app goes down. | +| `quiet` | Suppress some messages. (admittedly still not quiet) | +| `syncAll` | If this is set to true at the start of the app, the sync will start syncing all blocks from lastSync, and if lastSync is 0 it will start from whatever the endBlock or latest block in the blockchain is. | +| `patch` | If set to true and below value is set, sync will iterated through the # of blocks specified. | +| `patchBlocks` | If `patch` is set to true, the amount of block specified will be check from the latest one. | +| `useRichList` | If `useRichList` is set to true, explorer will update account balance for richlist page. | ### Mongodb Auth setting. @@ -177,13 +172,20 @@ The below will start both the web-gui and sync.js (which populates MongoDB with `npm start` You can leave sync.js running without app.js and it will sync and grab blocks based on config.json parameters -`node ./tools/sync.js` + +`npm run sync` Enabling stats requires running a separate process: -`node ./tools/stats.js` + +`npm run stats` Enabling richlist requires running a separate process: -`node ./tools/richlist.js` + +`npm run rich` + +Enabling price conversion requires running a separate process: + +`npm run price` You can configure intervals (how often a new data point is pulled) and range (how many blocks to go back) with the following: `RESCAN=100:7700000 node tools/stats.js` (New data point every 100 blocks. Go back 7,700,000 blocks). diff --git a/config.example.json b/config.example.json index ceb784a3b..1581d20aa 100644 --- a/config.example.json +++ b/config.example.json @@ -26,6 +26,7 @@ "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, + "useFiat": false, "miners": { "0xdf7d7e053933b5cc24372f878c90e62dadad5d42": "EtherMine", "0xc91716199ccde49dc4fafaeb68925127ac80443f": "F2Pool", diff --git a/db.js b/db.js index 06c3d7c00..e0fd7f1c1 100644 --- a/db.js +++ b/db.js @@ -77,6 +77,14 @@ var BlockStat = new Schema( "uncleCount": Number }, {collection: "BlockStat"}); +var Market = new Schema( +{ + "symbol": String, + "timestamp": Number, + "quoteBTC": Number, + "quoteUSD": Number +}, {collection: "Market"}); + // create indices Transaction.index({blockNumber:-1}); Transaction.index({from:1, blockNumber:-1}); @@ -88,17 +96,20 @@ Account.index({type:-1, balance:-1}); Block.index({miner:1}); Block.index({miner:1, blockNumber:-1}); Block.index({hash:1, number:-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.Promise = global.Promise; mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/explorerDB', { diff --git a/package.json b/package.json index 540c6dd49..c8983cc03 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,11 @@ "license": "MIT", "scripts": { "start": "concurrently \"node tools/sync.js \" \"node app.js\" ", + "app": "node app.js", + "sync": "node tools/sync.js", + "stats": "node tools/stats.js", + "rich": "node tools/richlist.js", + "price": "node tools/price.js", "pretest": "copyfiles app.js app/ ", "test": "mocha --exit" }, @@ -17,6 +22,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 b941992cb..e58099beb 100755 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -141,3 +141,6 @@ li.ng-scope { .search-form.open{width:100%!important;} } .page-spinner-bar{margin-top:-84px;margin-left:-98px;top:50%;left:50%;} +.mini-logo { + height: 1.2em; +} diff --git a/public/img/etc-mini-logo.svg b/public/img/etc-mini-logo.svg new file mode 100644 index 000000000..2c272644b --- /dev/null +++ b/public/img/etc-mini-logo.svg @@ -0,0 +1,289 @@ + + + + + Ethereum Classic Logo + + + + + + image/svg+xml + + Ethereum Classic Logo + + + + Ethereum Classic + + + + + Ethereum Classic + + + + + Ethereum Classic + + + Ethereum Classic Logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/views/address.html b/public/views/address.html index 0b37b87ab..95bd1b30b 100644 --- a/public/views/address.html +++ b/public/views/address.html @@ -7,21 +7,23 @@
    -
    +
    {{ addr.balance | number: 4 }} {{ settings.symbol }}
    {{ settings.symbol }} Balance -
    -
    +
    +
    + {{ addr.balanceUSD | currency : "$" : 4 }} USD balance +
    +
    {{ addr.mined }} Mined -
    -
    +
    +
    {{ addr.count }} Transactions -
    +
    -
    diff --git a/public/views/tx.html b/public/views/tx.html index 33fd8cb19..772b89356 100644 --- a/public/views/tx.html +++ b/public/views/tx.html @@ -29,9 +29,9 @@
    Creates: {{tx.creates}}
    Value:{{tx.value | number: 8}} {{ settings.symbol }}
    {{tx.value | number: 8}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }}
    Transaction fee:{{tx.txFee | number : 6}} {{ settings.symbol }}
    {{tx.txFee | number : 6}} {{ settings.symbol }} => {{ tx.txFeeUSD | currency : "USD $" : 10 }}
    Gas Limit:{{tx.gas | number}}
    Gas Used by Transaction: {{tx.gasUsed | number}}
    TimeStamp: {{tx.timestamp | timeDuration}} ago ({{tx.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }})
    From:{{tx.from}}
    To:{{tx.to}}
    From: + {{tx.from}} + {{tx.tokenFrom}} +
    To: + {{tx.to}} + {{tx.tokenTo}} +
    Creates: {{tx.creates}}
    Value:
    Value: {{tx.value | number: 8}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }}
    Token Value:{{tx.tokenValue | number: 8}} {{ tx.tokenSymbol }}
    Transaction fee: {{tx.txFee | number : 6}} {{ settings.symbol }} => {{ tx.txFeeUSD | currency : "USD $" : 10 }}
    Gas Limit:{{tx.gas | number}}
    Creates: {{tx.creates}}
    Value: {{tx.value | number: 8}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }}
    {{tx.value | number: 8}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }}
    Token Value: {{tx.tokenValue | number: 8}} {{ tx.tokenSymbol }}
    Transaction fee:{{tx.txFee | number : 6}} {{ settings.symbol }} => {{ tx.txFeeUSD | currency : "USD $" : 10 }}
    {{tx.txFee | number : 6}} {{ settings.symbol }} => {{ tx.txFeeUSD | currency : "USD $" : 10 }}
    Gas Limit:{{tx.gas | number}}
    Gas Used by Transaction: {{tx.gasUsed | number}}
    - - - - - - - - - - - - -
    TxHash Block From To {{ settings.symbol }} gas Age
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - -
    TxHash Block From To {{ settings.symbol }} gas
    {{t.transactionHash}} {{t.blockNumber}} - {{t.from}} {{t.to}} {{t.value}} {{t.gas}} {{t.type}} {{t.error}}
    -
    -
    - -
    +
    +
    + +
    +
    + + + + + + + + + + + + + + +
    TxHash Block From To {{ settings.symbol }} gas Age
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + +
    TxHash Block From To {{ settings.symbol }} gas
    {{t.transactionHash}} {{t.blockNumber}} + {{t.from}} {{t.to}} {{t.value}} {{t.gas}} {{t.type}} {{t.error}}
    +
    +
    +
    -
    -
    +
    + + diff --git a/public/views/block.html b/public/views/block.html index d8498976e..b8067f691 100644 --- a/public/views/block.html +++ b/public/views/block.html @@ -1,52 +1,64 @@
    -
    - - - - - - - - - - - - - - - - - +
    +
    Block Height<Prev {{block.number | number}} Next>
    TimeStamp{{block.timestamp | timeDuration}} ago ({{block.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }})
    Hash{{block.hash}}
    Parent Hash{{block.parentHash}}
    Sha3Uncles{{block.sha3Uncles}}
    Mined by{{block.miner}}
    Difficulty{{block.difficulty | totalDifficulty}}
    Total Difficulty{{block.totalDifficulty | totalDifficulty}}
    Gas Limit{{block.gasLimit | number}}
    Gas Used{{block.gasUsed | number}}
    Nonce{{block.nonce}}
    Extra Data{{block.extraData}} (Hex: {{block.extraDataHex}})
    Uncles{{block.uncles.length}} uncles - - - - - - -
    {{u}}
    -
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Block Height<Prev {{block.number | number}} Next>
    TimeStamp{{block.timestamp | timeDuration}} ago ({{block.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }})
    Hash{{block.hash}}
    Parent Hash + + {{block.parentHash}} +
    Sha3Uncles{{block.sha3Uncles}}
    Mined by{{block.miner}}
    Difficulty{{block.difficulty | totalDifficulty}}
    Total Difficulty{{block.totalDifficulty | totalDifficulty}}
    Gas Limit{{block.gasLimit | number}}
    Gas Used{{block.gasUsed | number}}
    Nonce{{block.nonce}}
    Extra Data{{block.extraData}} (Hex: {{block.extraDataHex}})
    Uncles{{block.uncles.length}} uncles + + + + + +
    {{u}}
    +
    -
    - +
    -
    - +
    +
    - - - + + + - - - + + + -
    Transactions
    Transactions
    {{t}}
    {{t}}
    -
    -
    + +
    + + diff --git a/public/views/contract-source.html b/public/views/contract-source.html index 76fb6f7f1..8f3c4d22b 100644 --- a/public/views/contract-source.html +++ b/public/views/contract-source.html @@ -5,40 +5,40 @@
    Verify And Publish Source Code. -

    - Contract Source Code Verified + Contract Source Code Verified

    -
    +
    Contract Name: {{contract.contractName}} -
    -
    +
    +
    Compiler Version: {{contract.compilerVersion}} -
    -
    +
    +
    Optimization Enabled: {{contract.optimization}} -
    +
    -
    + +
    Contract Source Code
    {{contract.sourceCode}}

    Contract ABI -
    {{contract.abi}}

    +
    {{contract.abi}}
    +
    -
    Contract Bytecode
    {{addr.bytecode}}
    - \ No newline at end of file + diff --git a/public/views/contract.html b/public/views/contract.html index 30650d682..2367a04bf 100644 --- a/public/views/contract.html +++ b/public/views/contract.html @@ -1,132 +1,117 @@
    -
    -
    - -
    - -
    -
    - -

    Verify and Publish Contract Source Code

    -
    - Enter Contract Source Code below.
    - If the compiled bytecode matches the Creation Address bytecode, the contract is then Verified and will be published online.
    +
    +
    +
    + +
    +
    + +

    Verify and Publish Contract Source Code

    +
    + Enter Contract Source Code below.
    + If the compiled bytecode matches the Creation Address bytecode, the contract is then Verified and will be published online.
    +
    +
    +
    +
    +
    + Contract Address +
    + +
    -
    -
    - -
    - Contract Address -
    - - -
    - {{errors.address}} -
    - -
    - Contract Name -
    - - -
    - {{errors.name}} -
    - - -
    - Compiler -
    - -
    - {{errors.version}} -
    -
    - Optimization Enabled - -
    - -
    - -
    -
    - Contract Code: - {{errors.code}} - -
    -
    - -
    -
    - Constructor Arguments ABI-encoded (OPTIONAL - Required for certain contracts only): - {{errors.abi}} - -
    -
    -
    - - - - -
    - -
    - -
    - -
    -
    -

    Contract Source Code Verified

    -

    - - View the verified result at {{contract.address}}. -

    -
    -
    -

    Unable to Verify Code

    -

    - - The compiled result does not match the input creation bytecode located at {{contract.address}}. -

    + {{errors.address}} +
    +
    + Contract Name +
    + +
    + {{errors.name}}
    -
    -
    -
    - Compiler Version: {{contract.compilerVersion}}
    - Optimization Enabled: {{contract.optimization}}
    - -
    -
    ContractName:
    -
    {{v.name}}
    - ContractBytecode:
    -
    {{v.bytecode}}
    - ContractABI:
    -
    {{v.abi}}
    -
    -
    - - +
    + Compiler +
    +
    + {{errors.version}}
    - +
    + Optimization Enabled + +
    +
    +
    +
    + Contract Code: + {{errors.code}} + +
    +
    +
    +
    + Constructor Arguments ABI-encoded (OPTIONAL - Required for certain contracts only): + {{errors.abi}} + +
    +
    +
    + + +
    + +
    + +
    +
    +
    +

    Contract Source Code Verified

    +

    + + View the verified result at {{contract.address}}. +

    +
    +
    +

    Unable to Verify Code

    +

    + + The compiled result does not match the input creation bytecode located at {{contract.address}}. +

    +
    +
    +
    +
    +
    + Compiler Version: {{contract.compilerVersion}}
    + Optimization Enabled: {{contract.optimization}}
    +
    +
    ContractName:
    +
    {{v.name}}
    + ContractBytecode:
    +
    {{v.bytecode}}
    + ContractABI:
    +
    {{v.abi}}
    +
    - - -
    -
    - - -
    \ No newline at end of file + +
    +
    +
    +
    + +
    + +
    diff --git a/public/views/created-tokens.html b/public/views/created-tokens.html index 031a9cde9..e52a4a04a 100644 --- a/public/views/created-tokens.html +++ b/public/views/created-tokens.html @@ -1,33 +1,32 @@ -
    - - - - - - - - - - - - - - - - - - - - - -
    TxHash Age Block To Amount
    {{t.transactionHash}} {{t.timestamp | timeDuration}} ago {{t.blockNumber}} {{t.to}} {{t.amount | number}} Created
    - -
    \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + +
    TxHash Age Block To Amount
    {{t.transactionHash}} {{t.timestamp | timeDuration}} ago {{t.blockNumber}} {{t.to}} {{t.amount | number}} Created
    + +
    diff --git a/public/views/err_404.html b/public/views/err_404.html index 6ae220f52..b559687af 100755 --- a/public/views/err_404.html +++ b/public/views/err_404.html @@ -1,13 +1,14 @@
    -
    -
    404
    -
    -

    Oops! You're lost.

    -

    We can not find the {{thing}} you are looking for. -

    - If you believe your {{thing}} is correct,
    - please report this error. -

    -
    +
    +
    404
    +
    +

    Oops! You're lost.

    +

    We can not find the {{thing}} you are looking for. +

    +

    + If you believe your {{thing}} is correct,
    + please report this error. +

    -
    \ No newline at end of file +
    +
    diff --git a/public/views/home.html b/public/views/home.html index 14cdb8cab..60f6b7c88 100755 --- a/public/views/home.html +++ b/public/views/home.html @@ -1,76 +1,74 @@ -
    -
    - -
    -
    -
    - - Blocks -
    -
    -
    - - -
    -
    -
    -
    -
    -
    - -
    - {{t.number}}
    - - {{t.timestamp | timeDuration }} ago -
    -
    -
    {{t.extraData}}
    - by {{t.miner}}
    - {{t.txn}} txns -
    -
    -
    -
    -
    +
    + +
    +
    +
    + + Blocks +
    +
    +
    + +
    - +
    -
    - -
    -
    -
    - - Transactions -
    -
    -
    - - -
    -
    +
    +
    +
    + +
    + {{t.number}}
    + + {{t.timestamp | timeDuration }} ago +
    +
    +
    {{t.extraData}}
    + by {{t.miner}}
    + {{t.txn}} txns
    -
    -
    -
    -
    -
    - TX {{t.hash}} -
    -
    {{t.timestamp | timeDuration }} ago
    -
    -
    - From {{t.from.substr(0,24)}}... - To {{t.to.substr(0,24)}}...
    -
    {{t.value}} {{settings.symbol}}
    -
    -
    - +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    + + Transactions +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    + TX {{t.hash}}
    +
    {{t.timestamp | timeDuration }} ago
    +
    +
    + From {{t.from.substr(0,24)}}... + To {{t.to.substr(0,24)}}...
    +
    {{t.value}} {{settings.symbol}}
    +
    - +
    + +
    diff --git a/public/views/simple-summary-stats.html b/public/views/simple-summary-stats.html index 537ef48c7..9d25c6e80 100644 --- a/public/views/simple-summary-stats.html +++ b/public/views/simple-summary-stats.html @@ -1,63 +1,63 @@
    -
    -
    -
    -
    - -
    -
    -

    - # - {{stats.blockHeight | number: 0 }} -

    - Block Height -
    -
    +
    +
    +
    +
    +
    +
    +

    + # + {{stats.blockHeight | number: 0 }} +

    + Block Height +
    +
    -
    -
    -
    -
    - -
    -
    -

    - {{stats.blockTime | number: 2}} s -

    - Block Time -
    -
    +
    +
    +
    +
    +
    + +
    +
    +

    + {{stats.blockTime | number: 2}} s +

    + Block Time
    +
    -
    -
    -
    -
    - -
    -
    -

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

    - Network Hashrate -
    -
    +
    +
    +
    +
    +
    +
    +
    +

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

    + Network Hashrate +
    +
    -
    -
    -
    -
    - -
    -
    -

    - {{stats.difficulty | totalDifficulty}} -

    - DIFFICULTY -
    -
    +
    +
    +
    +
    +
    + +
    +
    +

    + {{stats.difficulty | totalDifficulty}} +

    + DIFFICULTY
    +
    +
    diff --git a/public/views/site-notes.html b/public/views/site-notes.html index 9ac25cf74..34212195c 100644 --- a/public/views/site-notes.html +++ b/public/views/site-notes.html @@ -1,7 +1,7 @@
    -
    -
    -

    Welcome to ETC Explorer!

    -
    +
    +
    +

    Welcome to ETC Explorer!

    +
    diff --git a/public/views/stats/index.html b/public/views/stats/index.html index 4ad65d840..c5d87d2ca 100644 --- a/public/views/stats/index.html +++ b/public/views/stats/index.html @@ -1,13 +1,13 @@
    -
    - -
    -
    - - - - -
    -
    +
    + +
    +
    + + + + +
    +
    diff --git a/public/views/token.html b/public/views/token.html index e8d734923..c82fcd833 100644 --- a/public/views/token.html +++ b/public/views/token.html @@ -1,109 +1,115 @@
    -
    -
    -
    -
    -
    - - {{ token.balance | number: 10 }}
    - - {{ token.name }} Address Balance ({{ settings.symbol }}) -
    -
    - {{ token.total_supply | number:1 }} Total {{ token.symbol }} Tokens -
    - {{ token.total_holders | number:1 }}
    - Token Holders -
    -
    - {{ token.count }} Transactions -
    -
    -
    - -
    - -
    - Contract Address
    - {{token.address}} +
    +
    +
    +
    +
    + + {{ token.balance | number: 10 }}
    + + {{ token.name }} Address Balance ({{ settings.symbol }}) +
    +
    + {{ token.total_supply | number:1 }} Total {{ token.symbol }} Tokens +
    + {{ token.total_holders | number:1 }} +
    + Token Holders +
    +
    + {{ token.count }} Transactions +
    +
    +
    +
    + +
    + Contract Address
    + {{token.address}} +
    +
    +
    + +
    + +
    + + +
    +
    +
    + +
    +
    +

    Get {{ token.name }} Token Balance

    +
    + +
    + Enter Your Address +
    + + + +
    + {{errors.address}} +
    +
    + +
    + +
    +

    You have {{userTokens | number}} {{ token.symbol }} tokens.

    - -
    - -
    -
    - - -
    -
    - -
    - -
    -
    -

    Get {{ token.name }} Token Balance

    -
    -
    - Enter Your Address -
    - - - - -
    - {{errors.address}} -
    -
    -
    -
    -

    You have {{userTokens | number}} {{ token.symbol }} tokens.

    -
    -
    -
    -
    - -
    -
    - - - - - - - - - - - - - - -
    TxHash Block From To {{ settings.symbol }} gas Age
    -
    - -
    - -
    -
    +
    +
    + +
    + +
    + +
    + + + + + + + + + + + + + + +
    TxHash Block From To {{ settings.symbol }} gas Age
    +
    + +
    + +
    -
    + +
    +
    +
    diff --git a/public/views/tokenlist.html b/public/views/tokenlist.html index 4b4e90974..ece1553c4 100755 --- a/public/views/tokenlist.html +++ b/public/views/tokenlist.html @@ -1,13 +1,12 @@
    -
    - + \ No newline at end of file +
    +
    diff --git a/public/views/transfer-tokens.html b/public/views/transfer-tokens.html index d6bb6e712..ed67a70e4 100644 --- a/public/views/transfer-tokens.html +++ b/public/views/transfer-tokens.html @@ -1,35 +1,34 @@ -
    - - - - - - - - - - - - - - - - - - - - - - - -
    TxHash Age Block From To Amount
    {{t.transactionHash}} {{t.timestamp | timeDuration}} ago {{t.blockNumber}} {{t.from}} {{t.to}} {{t.amount | number}} Transfer
    - -
    \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + +
    TxHash Age Block From To Amount
    {{t.transactionHash}} {{t.timestamp | timeDuration}} ago {{t.blockNumber}} {{t.from}} {{t.to}} {{t.amount | number}} Transfer
    + +
    diff --git a/public/views/tx.html b/public/views/tx.html index 1f6a88477..7285e3413 100644 --- a/public/views/tx.html +++ b/public/views/tx.html @@ -1,76 +1,108 @@
    -
    - - - - - +
    Transaction Hash:{{tx.hash}}
    Status: +
    + + + + + + + + - - - - - - - + + + + + + + + + + + + - + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Transaction Hash:{{tx.hash}}
    Status: Failed (Error encountered during transaction !) Success Pending Not exist -
    Block: - {{tx.blockNumber | number}} - - -
    TimeStamp: {{tx.timestamp | timeDuration}} ago ({{tx.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }})
    From: +
    Block: + {{tx.blockNumber | number}} + + +
    TimeStamp: {{tx.timestamp | timeDuration}} ago ({{tx.datetime | date:'yyyy-MM-dd HH:mm:ss Z' }})
    From: {{tx.from}} {{tx.tokenFrom}} -
    To: +
    To: {{tx.to}} {{tx.tokenTo}} -
    Creates:{{tx.creates}}
    Value: {{tx.value | number: 8}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }}
    Token Value:{{tx.tokenValue | number: 8}} {{ tx.tokenSymbol }}
    Transaction fee:{{tx.txFee | number : 6}} {{ settings.symbol }} => {{ tx.txFeeUSD | currency : "USD $" : 10 }}
    Gas Limit:{{tx.gas | number}}
    Gas Used by Transaction:{{tx.gasUsed | number}}
    Gas Price:{{tx.gasPriceEther | number:9}} {{ settings.symbol }} ({{tx.gasPriceGwei | number}} Gwei)
    Creates:{{tx.creates}}
    Value: {{tx.value | number: 8}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }}
    Token Value:{{tx.tokenValue | number: 8}} {{ tx.tokenSymbol }}
    Transaction fee:{{tx.txFee | number : 6}} {{ settings.symbol }} => {{ tx.txFeeUSD | currency : "USD $" : 10 }}
    Gas Limit:{{tx.gas | number}}
    Gas Used by Transaction:{{tx.gasUsed | number}}
    Gas Price:{{tx.gasPriceEther | number:9}} {{ settings.symbol }} ({{tx.gasPriceGwei | number}} Gwei)
    Nonce:{{tx.nonce}}
    Input Data +
    {{tx.input}}
    +
    + + + + + + + + + + + + + + + + + + + - - -
    From To Amount Gas GasUsed
    {{t.from}} {{t.to}} {{t.value}} {{t.gas}} {{t.gasUsed}} {{t.type}} {{t.error}}
    Nonce:{{tx.nonce}}
    Input Data
    {{tx.input}}
    - - - - - - - - - - - - - - - - - - - - - - -
    From To Amount Gas GasUsed
    {{t.from}} {{t.to}} {{t.value}} {{t.gas}} {{t.gasUsed}} {{t.type}} {{t.error}}
    +
    -
    From a2ac93e47ab159a37ed5e8aab0b22be7e819c420 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 22:06:19 +0900 Subject: [PATCH 37/46] cleanup: add more configurable settings address review by @hackmod --- README.md | 4 +++- config.example.json | 3 ++- public/tpl/header.html | 2 +- public/views/address.html | 2 +- public/views/tx.html | 4 ++-- routes/web3relay.js | 14 +++++++++----- tools/sync.js | 14 ++++++++------ 7 files changed, 26 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 364702959..91a8a4f97 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,6 @@ Basic settings: "patch": true, "patchBlocks": 100, "bulkSize": 100, - "useRichList": true, "settings": { "symbol": "ETC", "name": "Ethereum Classic", @@ -60,6 +59,8 @@ Basic settings: "poweredbyCustom": false, "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, + "useRichList": true, + "useFiat": true, "miners": { "0xdf7d7e053933b5cc24372f878c90e62dadad5d42": "EtherMine", "0xc91716199ccde49dc4fafaeb68925127ac80443f": "F2Pool", @@ -104,6 +105,7 @@ Basic settings: | `patch` | If set to true and below value is set, sync will iterated through the # of blocks specified. | | `patchBlocks` | If `patch` is set to true, the amount of block specified will be check from the latest one. | | `useRichList` | If `useRichList` is set to true, explorer will update account balance for richlist page. | +| `useFiat` | If `useFiat` is set to true, explorer will show price for account & tx page. ( Disable for testnets )| ### Mongodb Auth setting. diff --git a/config.example.json b/config.example.json index b1e4dc2e6..347b672a5 100644 --- a/config.example.json +++ b/config.example.json @@ -8,7 +8,6 @@ "patch": true, "patchBlocks": 100, "bulkSize": 100, - "useRichList": true, "settings": { "symbol": "ETC", "name": "Ethereum Classic", @@ -27,6 +26,8 @@ "poweredbyEtcImage": "/img/powered-by-etcexplorer-w.png", "poweredbyEtc": true, "tokenList": "tokens.json", + "useRichList": true, + "useFiat": true, "miners": { "0xdf7d7e053933b5cc24372f878c90e62dadad5d42": "EtherMine", "0xc91716199ccde49dc4fafaeb68925127ac80443f": "F2Pool", diff --git a/public/tpl/header.html b/public/tpl/header.html index 815953d73..aae17b0fd 100755 --- a/public/tpl/header.html +++ b/public/tpl/header.html @@ -41,7 +41,7 @@
  • Home
  • -
  • +
  • Accounts
  • diff --git a/public/views/address.html b/public/views/address.html index 8bc099868..a4e526491 100644 --- a/public/views/address.html +++ b/public/views/address.html @@ -13,7 +13,7 @@ {{ settings.symbol }} Balance
    -
    +
    {{ addr.balanceUSD | currency : "$" : 4 }} USD balance
    diff --git a/public/views/tx.html b/public/views/tx.html index 7285e3413..695a0df28 100644 --- a/public/views/tx.html +++ b/public/views/tx.html @@ -48,7 +48,7 @@ Value: - {{tx.value | number: 8}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }} + {{tx.value | number: 8}} {{ settings.symbol }} => {{ tx.valueUSD | currency : "USD $" : 4 }} Token Value: @@ -56,7 +56,7 @@ Transaction fee: - {{tx.txFee | number : 6}} {{ settings.symbol }} => {{ tx.txFeeUSD | currency : "USD $" : 10 }} + {{tx.txFee | number : 6}} {{ settings.symbol }} => {{ tx.txFeeUSD | currency : "USD $" : 10 }} Gas Limit: diff --git a/routes/web3relay.js b/routes/web3relay.js index aa117a3ef..3da7b8f3a 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -129,9 +129,11 @@ exports.data = async (req, res) => { txResponse.gasPriceEther = etherUnits.toEther(new BigNumber(txResponse.gasPrice), 'wei'); txResponse.txFee = txResponse.gasPriceEther * txResponse.gasUsed; - const latestPrice = await Market.findOne().sort({ timestamp: -1 }); - txResponse.txFeeUSD = txResponse.txFee * latestPrice.quoteUSD; - txResponse.valueUSD = txResponse.value * latestPrice.quoteUSD; + if (config.settings.useFiat) { + const latestPrice = await Market.findOne().sort({timestamp: -1}); + txResponse.txFeeUSD = txResponse.txFee * latestPrice.quoteUSD; + txResponse.valueUSD = txResponse.value * latestPrice.quoteUSD; + } res.write(JSON.stringify(txResponse)); res.end(); @@ -199,8 +201,10 @@ exports.data = async (req, res) => { } } - const latestPrice = await Market.findOne().sort({ timestamp: -1 }); - addrData['balanceUSD'] = addrData.balance * latestPrice.quoteUSD; + if (config.settings.useFiat) { + const latestPrice = await Market.findOne().sort({timestamp: -1}); + addrData["balanceUSD"] = addrData.balance * latestPrice.quoteUSD; + } res.write(JSON.stringify(addrData)); res.end(); diff --git a/tools/sync.js b/tools/sync.js index 1f52b7cc2..3ddda9dbe 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -289,7 +289,7 @@ const writeTransactionsToDB = async (config, blockData, flush) => { if (bulk.length === 0 && accounts.length === 0) return; // update balances - if (config.useRichList && accounts.length > 0) { + if (config.settings.useRichList && accounts.length > 0) { asyncL.eachSeries(accounts, (account, eachCallback) => { const { blockNumber } = data[account]; // get contract account type @@ -589,7 +589,7 @@ if (config.patch === true) { // check NORICHLIST env // you can use it like as 'NORICHLIST=1 node tools/sync.js' to disable balance updater temporary. if (process.env.NORICHLIST) { - config.useRichList = false; + config.settings.useRichList = false; } // Start listening for latest blocks @@ -602,8 +602,10 @@ if (config.syncAll === true) { } // Start price sync on DB -getQuote(); - -setInterval(() => { +if (config.settings.useFiat) { getQuote(); -}, quoteInterval); + + setInterval(() => { + getQuote(); + }, quoteInterval); +} From c405f458cbab635303efe73c8669f6bcd13cbfc2 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 23:03:08 +0900 Subject: [PATCH 38/46] cleanup: more quiet mode for tools --- tools/richlist.js | 23 ++++++++++++++++++----- tools/stats.js | 24 ++++++++++++++++-------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/tools/richlist.js b/tools/richlist.js index 9283aa0dc..34d535468 100644 --- a/tools/richlist.js +++ b/tools/richlist.js @@ -50,7 +50,9 @@ function makeRichList(toBlock, blocks, updateCallback) { fromBlock = 0; } - console.log(`Scan accounts from ${fromBlock} to ${toBlock} ...`); + if (!('quiet' in config && config.quiet === true)) { + console.log(`Scan accounts from ${fromBlock} to ${toBlock} ...`); + } let ended = false; if (fromBlock == toBlock) { @@ -134,7 +136,9 @@ function makeRichList(toBlock, blocks, updateCallback) { console.info(`* ${len} / ${self.index + len} total accounts.`); if (updateCallback && (len >= 100 || ended)) { self.index += len; - console.log(`* update ${len} accounts ...`); + if (!('quiet' in config && config.quiet === true)) { + console.log(`* update ${len} accounts ...`); + } // split accounts into chunks to make proper sized json-rpc batch job. const accounts = Object.keys(self.accounts); @@ -294,7 +298,9 @@ function makeParityRichList(number, offset, blockNumber, updateCallback) { offset = lastAccount; const j = Object.keys(accounts).length; self.index += j; - console.log(` * ${j} / ${self.index} accounts, offset = ${offset}`); + if (!('quiet' in config && config.quiet === true)) { + console.log(` * ${j} / ${self.index} accounts, offset = ${offset}`); + } if (updateCallback) { updateCallback(accounts, blockNumber); } @@ -362,7 +368,9 @@ var bulkInsert = function (bulk) { console.log(`WARN: Fail to upsert (ignore) ${err}`); } - console.log(`* ${localbulk.length} accounts successfully updated.`); + if (!('quiet' in config && config.quiet === true)) { + console.log(`* ${localbulk.length} accounts successfully updated.`); + } if (bulk.length > 0) { setTimeout(() => { bulkInsert(bulk); @@ -374,7 +382,9 @@ var bulkInsert = function (bulk) { process.exit(9); } } else { - console.log(`* ${data.insertedCount} accounts successfully inserted.`); + if (!('quiet' in config && config.quiet === true)) { + console.log(`* ${data.insertedCount} accounts successfully inserted.`); + } if (bulk.length > 0) { setTimeout(() => { bulkInsert(bulk); @@ -461,6 +471,9 @@ async function startSync() { console.log('Error: Fail to load genesis address (ignore)'); } } + if ('quiet' in config && config.quiet === true) { + console.log('Quiet mode enabled'); + } makeRichList(latestBlock, 500, updateAccounts); } } diff --git a/tools/stats.js b/tools/stats.js index e746cc9e9..d92344f17 100644 --- a/tools/stats.js +++ b/tools/stats.js @@ -28,6 +28,9 @@ try { console.log(`Connecting ${config.nodeAddr}:${config.wsPort}...`); // Sets address for RPC WEB3 to connect to, usually your node IP address defaults ot localhost const web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://${config.nodeAddr}:${config.wsPort.toString()}`)); +if ('quiet' in config && config.quiet === true) { + console.log('Quiet mode enabled'); +} const updateStats = async (range, interval, rescan) => { let latestBlock = await web3.eth.getBlockNumber(); @@ -94,15 +97,17 @@ var checkBlockDBExistsThenWrite = function (web3, blockData, nextBlock, endNumbe 'uncleCount': blockData.uncles.length, }; new BlockStat(stat).save((err, s, count) => { - console.log(s); + if (!('quiet' in config && config.quiet === true)) { + console.log(s); + } if (typeof err !== 'undefined' && err) { - console.log(`${'Error: Aborted due to error on ' + - 'block number '}${blockData.number.toString()}: ${ + console.log(`${'Error: Aborted due to error on ' + 'block number '}${blockData.number.toString()}: ${ err}`); process.exit(9); } else { - console.log(`DB successfully written for block number ${ - blockData.number.toString()}`); + if (!('quiet' in config && config.quiet === true)) { + console.log(`DB successfully written for block number ${blockData.number.toString()}`); + } getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan); } }); @@ -110,11 +115,14 @@ var checkBlockDBExistsThenWrite = function (web3, blockData, nextBlock, endNumbe if (rescan || !nextBlock) { getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan); if (nextBlock) { - console.log(`WARN: block number: ${blockData.number.toString()} already exists in DB.`); + if (!('quiet' in config && config.quiet === true)) { + console.log(`WARN: block number: ${blockData.number.toString()} already exists in DB.`); + } } } else { - console.error(`Aborting because block number: ${blockData.number.toString() - } already exists in DB.`); + if (!('quiet' in config && config.quiet === true)) { + console.error(`Aborting because block number: ${blockData.number.toString()} already exists in DB.`); + } } } From 2ecd60021ef8c2bfc36b103b740aac8e2b5936c3 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Fri, 22 Mar 2019 23:47:40 +0900 Subject: [PATCH 39/46] cleanup: more eslint on files --- package.json | 4 ++-- routes/web3relay.js | 6 +++--- test/index.js | 9 ++++----- test/units/apps.js | 28 ++++++++++++++-------------- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index a64c9dba1..2020a9614 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "stats": "node tools/stats.js", "rich": "node tools/richlist.js", "test": "mocha --exit", - "lint:check": "concurrently \"eslint *.js ./lib/*.js ./routes/*.js ./tools/*.js \" \"html-linter --config html-linter.json\" ", - "lint:fix": "eslint *.js ./lib/*.js ./routes/*.js ./tools/*.js --fix" + "lint:check": "concurrently \"eslint *.js ./lib/*.js ./test/*.js ./test/units/*.js ./routes/*.js ./tools/*.js \" \"html-linter --config html-linter.json\" ", + "lint:fix": "eslint *.js ./lib/*.js ./test/*.js ./test/units/*.js ./routes/*.js ./tools/*.js --fix" }, "dependencies": { "bignumber.js": "^8.1.1", diff --git a/routes/web3relay.js b/routes/web3relay.js index 3da7b8f3a..96176f092 100644 --- a/routes/web3relay.js +++ b/routes/web3relay.js @@ -130,7 +130,7 @@ exports.data = async (req, res) => { txResponse.txFee = txResponse.gasPriceEther * txResponse.gasUsed; if (config.settings.useFiat) { - const latestPrice = await Market.findOne().sort({timestamp: -1}); + const latestPrice = await Market.findOne().sort({ timestamp: -1 }); txResponse.txFeeUSD = txResponse.txFee * latestPrice.quoteUSD; txResponse.valueUSD = txResponse.value * latestPrice.quoteUSD; } @@ -202,8 +202,8 @@ exports.data = async (req, res) => { } if (config.settings.useFiat) { - const latestPrice = await Market.findOne().sort({timestamp: -1}); - addrData["balanceUSD"] = addrData.balance * latestPrice.quoteUSD; + const latestPrice = await Market.findOne().sort({ timestamp: -1 }); + addrData['balanceUSD'] = addrData.balance * latestPrice.quoteUSD; } res.write(JSON.stringify(addrData)); diff --git a/test/index.js b/test/index.js index f10b66ce1..83522bc4f 100644 --- a/test/index.js +++ b/test/index.js @@ -1,14 +1,13 @@ -var assert = require('assert'); - +const assert = require('assert'); //* load unit tests *// -var app = require('./units/apps'); +const app = require('./units/apps'); //* end unit tests *// /* tests to run (add tests here) */ -describe('Global functions', function() { - app +describe('Global functions', () => { + app; }); diff --git a/test/units/apps.js b/test/units/apps.js index 61b7fc7a7..2efae94e8 100644 --- a/test/units/apps.js +++ b/test/units/apps.js @@ -1,10 +1,10 @@ -var assert = require('assert'); -var expect = require('chai').expect; -var request = require('request'); +const assert = require('assert'); +const { expect } = require('chai'); +const request = require('request'); //* unit under test *// -var app = require('../../app.js'); +const app = require('../../app.js'); /* Description: * tests that the express server is basically functional @@ -12,24 +12,24 @@ var app = require('../../app.js'); module.exports = -describe("Classic Explorer Server Tests", function() { +describe('Classic Explorer Server Tests', () => { - //ping the index page to ensure it is running + //ping the index page to ensure it is running - describe("Test index page", function() { - var url = "http://localhost:3000/"; - it("returns status 200", function(done) { - request(url, function(error, response, body) { + describe('Test index page', () => { + const url = 'http://localhost:3000/'; + it('returns status 200', (done) => { + request(url, (error, response, body) => { expect(response.statusCode).to.equal(200); done(); }); }); - // return the 404 on a bad page request + // return the 404 on a bad page request - var badurl = "http://localhost:3000/ethereum_classic_is_best_classic"; - it("bad pages go to index", function(done) { - request(badurl, function(error, response, body) { + const badurl = 'http://localhost:3000/ethereum_classic_is_best_classic'; + it('bad pages go to index', (done) => { + request(badurl, (error, response, body) => { expect(response.statusCode).to.equal(200); done(); }); From 04a05c02043b7ceaf9e9c20c8ca5061effcfe4b0 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Sun, 24 Mar 2019 06:40:05 +0900 Subject: [PATCH 40/46] cleanup: apply quiet mode for live patch --- tools/sync.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/sync.js b/tools/sync.js index 3ddda9dbe..cad19ff43 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -317,10 +317,12 @@ const writeTransactionsToDB = async (config, blockData, flush) => { let n = 0; accounts.forEach((account) => { n++; - if (n <= 5) { - console.log(` - upsert ${account} / balance = ${data[account].balance}`); - } else if (n === 6) { - console.log(` (...) total ${accounts.length} accounts updated.`); + if (!('quiet' in config && config.quiet === true)) { + if (n <= 5) { + console.log(` - upsert ${account} / balance = ${data[account].balance}`); + } else if (n === 6) { + console.log(` (...) total ${accounts.length} accounts updated.`); + } } // upsert account Account.collection.update({ address: account }, { $set: data[account] }, { upsert: true }); @@ -498,7 +500,9 @@ const runPatcher = async (config, startBlock, endBlock) => { const missingBlocks = endBlock - startBlock + 1; if (missingBlocks > 0) { - console.log(`Patching from #${startBlock} to #${endBlock}`); + if (!('quiet' in config && config.quiet === true)) { + console.log(`Patching from #${startBlock} to #${endBlock}`); + } let patchBlock = startBlock; let count = 0; while (count < config.patchBlocks && patchBlock <= endBlock) { From c1c398d636ec2753a305f65a9b8523f31251358b Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Sun, 24 Mar 2019 07:57:29 +0900 Subject: [PATCH 41/46] cleanup: limit tx.status for post byzantium blocks * remove internal tx table field as they are shown on main table already --- public/views/tx.html | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/public/views/tx.html b/public/views/tx.html index 695a0df28..3fca393a2 100644 --- a/public/views/tx.html +++ b/public/views/tx.html @@ -11,9 +11,7 @@ Status: Failed (Error encountered during transaction !) - Success - Pending - Not exist + Success @@ -81,28 +79,6 @@ - - - - - - - - - - - - - - - - - - - - - -
    From To Amount Gas GasUsed
    {{t.from}} {{t.to}} {{t.value}} {{t.gas}} {{t.gasUsed}} {{t.type}} {{t.error}}
  • From 116b3429c220f73940c8ab479e8fd05b275d1448 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Sun, 24 Mar 2019 16:57:21 +0900 Subject: [PATCH 42/46] cleanup: use human-standard-token-abi from npm to fetch erc20 token abi * to-do do the same thing for other contracts --- package-lock.json | 5 +++++ package.json | 1 + tools/sync.js | 25 ++----------------------- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 784aa7bc2..c4d847dc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2339,6 +2339,11 @@ "sshpk": "^1.7.0" } }, + "human-standard-token-abi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/human-standard-token-abi/-/human-standard-token-abi-2.0.0.tgz", + "integrity": "sha512-m1f5DiIvqaNmpgphNqx2OziyTCj4Lvmmk28uMSxGWrOc9/lMpAKH8UcMPhvb13DMNZPzxn07WYFhxOGKuPLryg==" + }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", diff --git a/package.json b/package.json index 2020a9614..cf1452920 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "concurrently": "4.1.0", "ejs": "2.6.1", "express": "^4.16.4", + "human-standard-token-abi": "^2.0.0", "mongoose": "^4.13.18", "morgan": "^1.9.1", "node-fetch": "^2.3.0", diff --git a/tools/sync.js b/tools/sync.js index cad19ff43..c24849b9f 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -11,6 +11,8 @@ const _ = require('lodash'); const asyncL = require('async'); const Web3 = require('web3'); +const ERC20ABI = require('human-standard-token-abi'); + const fetch = require('node-fetch'); const mongoose = require('mongoose'); @@ -23,29 +25,6 @@ const Account = mongoose.model('Account'); const Contract = mongoose.model('Contract'); const TokenTransfer = mongoose.model('TokenTransfer'); -const ERC20ABI = [{ - 'constant': true, 'inputs': [], 'name': 'name', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', -}, { - 'constant': false, 'inputs': [{ 'name': '_spender', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'approve', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function', -}, { - 'constant': true, 'inputs': [], 'name': 'totalSupply', 'outputs': [{ 'name': '', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', -}, { - 'constant': false, 'inputs': [{ 'name': '_from', 'type': 'address' }, { 'name': '_to', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'transferFrom', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function', -}, { - 'constant': true, 'inputs': [], 'name': 'decimals', 'outputs': [{ 'name': '', 'type': 'uint8' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', -}, { - 'constant': true, 'inputs': [{ 'name': '_owner', 'type': 'address' }], 'name': 'balanceOf', 'outputs': [{ 'name': 'balance', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', -}, { - 'constant': true, 'inputs': [], 'name': 'symbol', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', -}, { - 'constant': false, 'inputs': [{ 'name': '_to', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'transfer', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function', -}, { - 'constant': true, 'inputs': [{ 'name': '_owner', 'type': 'address' }, { 'name': '_spender', 'type': 'address' }], 'name': 'allowance', 'outputs': [{ 'name': '', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function', -}, { 'payable': true, 'stateMutability': 'payable', 'type': 'fallback' }, { - 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'owner', 'type': 'address' }, { 'indexed': true, 'name': 'spender', 'type': 'address' }, { 'indexed': false, 'name': 'value', 'type': 'uint256' }], 'name': 'Approval', 'type': 'event', -}, { - 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'from', 'type': 'address' }, { 'indexed': true, 'name': 'to', 'type': 'address' }, { 'indexed': false, 'name': 'value', 'type': 'uint256' }], 'name': 'Transfer', 'type': 'event', -}]; const ERC20_METHOD_DIC = { '0xa9059cbb': 'transfer', '0xa978501e': 'transferFrom' }; /** From 0d84e6437e8382f3e7c4f06178b9eae06957ae82 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Sun, 24 Mar 2019 18:28:21 +0900 Subject: [PATCH 43/46] cleanup: improve tools/sync.js --- tools/sync.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tools/sync.js b/tools/sync.js index c24849b9f..91392d248 100644 --- a/tools/sync.js +++ b/tools/sync.js @@ -75,21 +75,20 @@ const normalizeTX = async (txData, receipt, blockData) => { timestamp: blockData.timestamp, }; - if (receipt.status) tx.status = receipt.status; + if (receipt.status) { + tx.status = receipt.status; + } if (txData.to) { tx.to = txData.to.toLowerCase(); return tx; - } - if (tx.creates) { + } else if (txData.creates) { tx.creates = txData.creates.toLowerCase(); return tx; - } - if (receipt && receipt.contractAddress) { + } else { tx.creates = receipt.contractAddress.toLowerCase(); + return tx; } - return tx; - }; /** @@ -155,7 +154,12 @@ const writeTransactionsToDB = async (config, blockData, flush) => { if (txData.input && txData.input.length > 2) { // Contact creation tx if (txData.to === null) { - contractAddress = txData.creates.toLowerCase(); + // Support Parity & Geth case + if (txData.creates) { + contractAddress = txData.creates.toLowerCase(); + } else { + contractAddress = receipt.contractAddress.toLowerCase(); + } const contractdb = {}; let isTokenContract = true; const Token = new web3.eth.Contract(ERC20ABI, contractAddress); @@ -168,6 +172,7 @@ const writeTransactionsToDB = async (config, blockData, flush) => { isTokenContract = false; } else { try { + // ERC20 & ERC223 Token Standard compatible format contractdb.tokenName = await Token.methods.name().call(); contractdb.decimals = await Token.methods.decimals().call(); contractdb.symbol = await Token.methods.symbol().call(); From abe658863280b98e2d08ce947ff05fc8b7d28227 Mon Sep 17 00:00:00 2001 From: Cody Burns Date: Fri, 4 Sep 2020 15:06:20 -0500 Subject: [PATCH 44/46] Update Dockerfile require node 8 to build --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3d95fcafd..c3ed81157 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:latest +FROM node:8 COPY . / From c10059a18aa8e1e2caebb959a04f73ff44135624 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2020 20:12:16 +0000 Subject: [PATCH 45/46] build(deps): bump tree-kill from 1.2.1 to 1.2.2 Bumps [tree-kill](https://github.com/pkrumins/node-tree-kill) from 1.2.1 to 1.2.2. - [Release notes](https://github.com/pkrumins/node-tree-kill/releases) - [Commits](https://github.com/pkrumins/node-tree-kill/compare/v1.2.1...v1.2.2) Signed-off-by: dependabot[bot] --- package-lock.json | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index c4d847dc4..cbb785150 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5152,9 +5152,9 @@ } }, "tree-kill": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", - "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" }, "tslib": { "version": "1.9.3", @@ -5639,6 +5639,18 @@ "underscore": "1.8.3", "web3-core-helpers": "1.0.0-beta.37", "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + }, + "dependencies": { + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible", + "requires": { + "debug": "^2.2.0", + "nan": "^2.3.3", + "typedarray-to-buffer": "^3.1.2", + "yaeti": "^0.0.6" + } + } } }, "web3-shh": { @@ -5673,16 +5685,6 @@ } } }, - "websocket": { - "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", - "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible", - "requires": { - "debug": "^2.2.0", - "nan": "^2.3.3", - "typedarray-to-buffer": "^3.1.2", - "yaeti": "^0.0.6" - } - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", From 3ebb12353073d558dbd1c392c7b1bc79a779790f Mon Sep 17 00:00:00 2001 From: benjioh5 Date: Thu, 4 Feb 2021 20:19:31 +0900 Subject: [PATCH 46/46] fix... --- db.js | 110 +--------------------------------------------------------- 1 file changed, 1 insertion(+), 109 deletions(-) diff --git a/db.js b/db.js index cdf92ca7f..34880e69e 100644 --- a/db.js +++ b/db.js @@ -1,4 +1,3 @@ -<<<<<<< HEAD const mongoose = require('mongoose'); const { Schema } = mongoose; @@ -154,111 +153,4 @@ mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/explorerDB', { // pass: 'yourdbpasscode' }); -// mongoose.set('debug', true); -======= -var mongoose = require( 'mongoose' ); -var Schema = mongoose.Schema; - -var Block = new Schema( -{ - "number": {type: Number, index: {unique: true}}, - "hash": String, - "parentHash": String, - "nonce": String, - "sha3Uncles": String, - "logsBloom": String, - "transactionsRoot": String, - "stateRoot": String, - "receiptRoot": String, - "miner": String, - "difficulty": String, - "totalDifficulty": String, - "size": Number, - "extraData": String, - "gasLimit": Number, - "gasUsed": Number, - "timestamp": Number, - "blockTime": Number, - "uncles": [String] -}); - -var Account = new Schema( -{ - "address": {type: String, index: {unique: true}}, - "balance": Number, - "blockNumber": Number, - "type": {type: Number, default: 0} // address: 0x0, contract: 0x1 -}); - -var Contract = new Schema( -{ - "address": {type: String, index: {unique: true}}, - "creationTransaction": String, - "contractName": String, - "compilerVersion": String, - "optimization": Boolean, - "sourceCode": String, - "abi": String, - "byteCode": String -}, {collection: "Contract"}); - -var Transaction = new Schema( -{ - "hash": {type: String, index: {unique: true}}, - "nonce": Number, - "blockHash": String, - "blockNumber": Number, - "transactionIndex": Number, - "from": String, - "to": String, - "creates": String, - "value": String, - "gas": Number, - "gasPrice": String, - "timestamp": Number, - "input": String -}, {collection: "Transaction"}); - -var BlockStat = new Schema( -{ - "number": {type: Number, index: {unique: true}}, - "timestamp": Number, - "difficulty": String, - "hashrate": String, - "txCount": Number, - "gasUsed": Number, - "gasLimit": Number, - "miner": String, - "blockTime": Number, - "uncleCount": Number -}); - -// create indices -Transaction.index({blockNumber:-1}); -Transaction.index({from:1, blockNumber:-1}); -Transaction.index({to:1, blockNumber:-1}); -Transaction.index({creates:1, blockNumber:-1}); -Account.index({balance:-1}); -Account.index({balance:-1, blockNumber:-1}); -Account.index({type:-1, balance:-1}); -Block.index({miner:1}); -Block.index({miner:1, blockNumber:-1}); - -mongoose.model('BlockStat', BlockStat); -mongoose.model('Block', Block); -mongoose.model('Account', Account); -mongoose.model('Contract', Contract); -mongoose.model('Transaction', Transaction); -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'); - -mongoose.Promise = global.Promise; -mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/blockDB', { - useMongoClient: true -}); - -// mongoose.set('debug', true); ->>>>>>> 0b8c4c3885e581183f3777ca1993136c3386be4e +// mongoose.set('debug', true); \ No newline at end of file