aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrandon Millman <brandon.millman@gmail.com>2017-11-21 05:12:15 +0800
committerBrandon Millman <brandon.millman@gmail.com>2017-12-13 07:45:22 +0800
commitbbb768c5cfa8bf713670608f859debae42b42898 (patch)
tree40ae6f11995fa44a1ee58092a8308faac63abec4
parent5678196706a63d27fc5b00b5224c8213510e76f0 (diff)
downloaddexon-0x-contracts-bbb768c5cfa8bf713670608f859debae42b42898.tar.gz
dexon-0x-contracts-bbb768c5cfa8bf713670608f859debae42b42898.tar.zst
dexon-0x-contracts-bbb768c5cfa8bf713670608f859debae42b42898.zip
Add kovan faucet project into the mono repo
-rw-r--r--.gitignore3
-rw-r--r--packages/0x.js/tsconfig.json3
-rw-r--r--packages/assert/tsconfig.json3
-rw-r--r--packages/connect/tsconfig.json3
-rw-r--r--packages/json-schemas/tsconfig.json3
-rw-r--r--packages/kovan-faucets/Dockerfile13
-rw-r--r--packages/kovan-faucets/README.md64
-rw-r--r--packages/kovan-faucets/gulpfile.js98
-rw-r--r--packages/kovan-faucets/package.json43
-rw-r--r--packages/kovan-faucets/scripts/postpublish.js14
-rw-r--r--packages/kovan-faucets/src/ts/configs.ts10
-rw-r--r--packages/kovan-faucets/src/ts/error_reporter.ts40
-rw-r--r--packages/kovan-faucets/src/ts/ether_request_queue.ts26
-rw-r--r--packages/kovan-faucets/src/ts/global.d.ts15
-rw-r--r--packages/kovan-faucets/src/ts/handler.ts88
-rw-r--r--packages/kovan-faucets/src/ts/id_management.ts27
-rw-r--r--packages/kovan-faucets/src/ts/request_queue.ts53
-rw-r--r--packages/kovan-faucets/src/ts/server.ts27
-rw-r--r--packages/kovan-faucets/src/ts/utils.ts10
-rw-r--r--packages/kovan-faucets/src/ts/zrx_request_queue.ts38
-rw-r--r--packages/kovan-faucets/tsconfig.json15
-rw-r--r--packages/kovan-faucets/tslint.json5
-rw-r--r--yarn.lock371
23 files changed, 948 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore
index 11fbb8499..24b8d044f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,3 +68,6 @@ generated_docs/
TODO.md
packages/website/public/bundle*
+
+# generated binaries
+bin/
diff --git a/packages/0x.js/tsconfig.json b/packages/0x.js/tsconfig.json
index a5da86b88..b02dd3ac8 100644
--- a/packages/0x.js/tsconfig.json
+++ b/packages/0x.js/tsconfig.json
@@ -8,7 +8,8 @@
"declaration": true,
"noImplicitAny": true,
"experimentalDecorators": true,
- "strictNullChecks": true
+ "strictNullChecks": true,
+ "types": [ "jsonschema", "lodash", "mocha", "node", "sinon", "uuid"]
},
"include": [
"./src/**/*",
diff --git a/packages/assert/tsconfig.json b/packages/assert/tsconfig.json
index 709e20154..0de9af8f0 100644
--- a/packages/assert/tsconfig.json
+++ b/packages/assert/tsconfig.json
@@ -7,7 +7,8 @@
"sourceMap": true,
"declaration": true,
"noImplicitAny": true,
- "strictNullChecks": true
+ "strictNullChecks": true,
+ "types": [ "lodash", "mocha", "valid-url" ]
},
"include": [
"./src/**/*",
diff --git a/packages/connect/tsconfig.json b/packages/connect/tsconfig.json
index a6c8277f8..9648e5436 100644
--- a/packages/connect/tsconfig.json
+++ b/packages/connect/tsconfig.json
@@ -7,7 +7,8 @@
"sourceMap": true,
"declaration": true,
"noImplicitAny": true,
- "strictNullChecks": true
+ "strictNullChecks": true,
+ "types": [ "fetch-mock", "lodash", "mocha", "query-string", "websocket" ]
},
"include": [
"./src/**/*",
diff --git a/packages/json-schemas/tsconfig.json b/packages/json-schemas/tsconfig.json
index 40c2f0c8c..0a0513d01 100644
--- a/packages/json-schemas/tsconfig.json
+++ b/packages/json-schemas/tsconfig.json
@@ -7,7 +7,8 @@
"sourceMap": true,
"declaration": true,
"noImplicitAny": true,
- "strictNullChecks": true
+ "strictNullChecks": true,
+ "types": [ "lodash.foreach", "lodash.values", "mocha"]
},
"include": [
"./src/**/*",
diff --git a/packages/kovan-faucets/Dockerfile b/packages/kovan-faucets/Dockerfile
new file mode 100644
index 000000000..6d6ddc192
--- /dev/null
+++ b/packages/kovan-faucets/Dockerfile
@@ -0,0 +1,13 @@
+FROM node
+
+WORKDIR /src
+
+COPY package.json .
+RUN npm i
+RUN npm install forever -g
+
+COPY . .
+
+EXPOSE 3000
+
+CMD ["forever", "./bin/server.js"]
diff --git a/packages/kovan-faucets/README.md b/packages/kovan-faucets/README.md
new file mode 100644
index 000000000..72c1368fb
--- /dev/null
+++ b/packages/kovan-faucets/README.md
@@ -0,0 +1,64 @@
+Test Ether Faucet
+----------------------
+
+This faucet dispenses 0.1 test ether to one recipient per second. It has a max queue size of 1000.
+
+
+## Install
+
+Install project dependencies:
+
+```
+npm install
+```
+
+## Start
+
+Set the following environment variables:
+
+```
+export FAUCET_ENVIRONMENT=development
+export DISPENSER_ADDRESS=0x5409ed021d9299bf6814279a6a1411a7e866a631
+export DISPENSER_PRIVATE_KEY=f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d
+export FAUCET_ROLLBAR_ACCESS_KEY={GET_THIS_FROM_ROLLBAR_ACCOUNT_SETTINGS}
+```
+
+Note: The above public/private keys exist when running `testrpc` with the following option `--mnemonic concert load couple harbor equip island argue ramp clarify fence smart topic`.
+
+The real production key with kovan ETH exist in 1password
+
+```
+npm run dev
+```
+
+## Endpoints
+
+```GET /rain/:recipient_address```
+
+Where recipient_address is a hex encoded Ethereum address prefixed with `0x`.
+
+```GET /queue```
+
+Returns the status of the queue
+
+```javascript
+{
+ "full": false,
+ "size": 0
+}
+```
+
+## Docker configs
+
+```
+docker run -d \
+-p 80:3000 \
+--name kovan-faucets \
+--log-opt max-size=100m \
+--log-opt max-file=20 \
+-e DISPENSER_ADDRESS=$DISPENSER_ADDRESS \
+-e DISPENSER_PRIVATE_KEY=$DISPENSER_PRIVATE_KEY \
+-e FAUCET_ROLLBAR_ACCESS_KEY=$FAUCET_ROLLBAR_ACCESS_KEY \
+-e FAUCET_ENVIRONMENT=production \
+kovan-faucets
+```
diff --git a/packages/kovan-faucets/gulpfile.js b/packages/kovan-faucets/gulpfile.js
new file mode 100644
index 000000000..3e80e656e
--- /dev/null
+++ b/packages/kovan-faucets/gulpfile.js
@@ -0,0 +1,98 @@
+const gulp = require('gulp');
+const nodemon = require('nodemon');
+const path = require('path');
+const webpack = require('webpack');
+const fs = require('fs');
+
+const nodeModules = {};
+fs.readdirSync('node_modules')
+ .filter(function(x) {
+ return ['.bin'].indexOf(x) === -1;
+ })
+ .forEach(function(mod) {
+ nodeModules[mod] = 'commonjs ' + mod;
+ });
+
+const config = {
+ target: 'node',
+ entry: ['./src/ts/server.ts'],
+ output: {
+ path: path.join(__dirname, '/bin'),
+ filename: 'server.js',
+ },
+ devtool: 'source-map',
+ resolve: {
+ modules: [
+ path.join(__dirname, '/src/ts'),
+ 'node_modules',
+ ],
+ extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
+ alias: {
+ ts: path.join(__dirname, '/src/ts'),
+ contract_artifacts: path.join(__dirname, '/src/contract_artifacts'),
+ },
+ },
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ loader: 'source-map-loader',
+ },
+ {
+ test: /\.tsx?$/,
+ loader: 'awesome-typescript-loader',
+ },
+ ],
+ },
+ plugins: [
+ new webpack.BannerPlugin({
+ banner: 'require("source-map-support").install();',
+ raw: true,
+ entryOnly: false,
+ }),
+ ],
+ externals: nodeModules,
+ watchOptions: {
+ ignored: /bin|node_modules|transpiled/
+ },
+};
+
+gulp.task('build', function(done) {
+ webpack(config).run(onBuild(done));
+});
+
+gulp.task('watch', function() {
+ webpack(config).watch(100, function(err, stats) {
+ onBuild()(err, stats);
+ nodemon.restart();
+ });
+});
+
+gulp.task('run', ['watch'], function() {
+ nodemon({
+ execMap: {
+ js: 'node',
+ },
+ script: path.join(__dirname, 'bin/server'),
+ ignore: ['*'],
+ watch: ['foo/'],
+ ext: 'noop',
+ }).on('restart', function() {
+ console.log('Restarted!');
+ });
+});
+
+function onBuild(done) {
+ return function(err, stats) {
+ if(err) {
+ console.log('Error', err);
+ }
+ else {
+ console.log(stats.toString());
+ }
+
+ if(done) {
+ done();
+ }
+ }
+}
diff --git a/packages/kovan-faucets/package.json b/packages/kovan-faucets/package.json
new file mode 100644
index 000000000..db1e1675d
--- /dev/null
+++ b/packages/kovan-faucets/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "@0xproject/erc20-token-faucet",
+ "version": "1.0.0",
+ "description": "A faucet micro-service that dispenses test ERC20 tokens",
+ "main": "server.js",
+ "scripts": {
+ "build": "node ../../node_modules/gulp/bin/gulp.js build",
+ "dev": "node ../../node_modules/gulp/bin/gulp.js run",
+ "start": "node ./bin/server.js",
+ "lint": "tslint src/**/*.ts",
+ "clean": "shx rm -rf bin"
+ },
+ "author": "Fabio Berger",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "0x.js": "~0.25.1",
+ "bignumber.js": "~4.1.0",
+ "body-parser": "^1.17.1",
+ "es6-promisify": "^5.0.0",
+ "ethereumjs-tx": "^1.2.5",
+ "express": "^4.15.2",
+ "lodash": "^4.17.4",
+ "rollbar": "^0.6.5",
+ "web3": "^0.20.0",
+ "web3-provider-engine": "^13.0.1"
+ },
+ "devDependencies": {
+ "@0xproject/tslint-config": "^0.1.0",
+ "@types/body-parser": "^1.16.1",
+ "@types/es6-promise": "^0.0.33",
+ "@types/express": "^4.0.35",
+ "@types/lodash": "^4.14.57",
+ "awesome-typescript-loader": "^3.1.3",
+ "gulp": "^3.9.1",
+ "nodemon": "^1.11.0",
+ "shx": "^0.2.2",
+ "source-map-loader": "^0.2.0",
+ "tslint": "5.8.0",
+ "typescript": "~2.6.1",
+ "web3-typescript-typings": "^0.7.1",
+ "webpack": "^3.1.0"
+ }
+}
diff --git a/packages/kovan-faucets/scripts/postpublish.js b/packages/kovan-faucets/scripts/postpublish.js
new file mode 100644
index 000000000..7fa452b08
--- /dev/null
+++ b/packages/kovan-faucets/scripts/postpublish.js
@@ -0,0 +1,14 @@
+const postpublish_utils = require('../../../scripts/postpublish_utils');
+const packageJSON = require('../package.json');
+
+const subPackageName = packageJSON.name;
+
+postpublish_utils.getLatestTagAndVersionAsync(subPackageName)
+ .then(function(result) {
+ const releaseName = postpublish_utils.getReleaseName(subPackageName, result.version);
+ const assets = [];
+ return postpublish_utils.publishReleaseNotes(result.tag, releaseName, assets);
+ })
+ .catch (function(err) {
+ throw err;
+ });
diff --git a/packages/kovan-faucets/src/ts/configs.ts b/packages/kovan-faucets/src/ts/configs.ts
new file mode 100644
index 000000000..2b130446d
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/configs.ts
@@ -0,0 +1,10 @@
+export const configs = {
+ DISPENSER_ADDRESS: process.env.DISPENSER_ADDRESS.toLowerCase(),
+ DISPENSER_PRIVATE_KEY: process.env.DISPENSER_PRIVATE_KEY,
+ ENVIRONMENT: process.env.FAUCET_ENVIRONMENT,
+ ROLLBAR_ACCESS_KEY: process.env.FAUCET_ROLLBAR_ACCESS_KEY,
+ RPC_URL: process.env.FAUCET_ENVIRONMENT === 'development' ?
+ 'http://127.0.0.1:8545' :
+ 'https://kovan.infura.io/T5WSC8cautR4KXyYgsRs',
+ ZRX_TOKEN_ADDRESS: '0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570',
+};
diff --git a/packages/kovan-faucets/src/ts/error_reporter.ts b/packages/kovan-faucets/src/ts/error_reporter.ts
new file mode 100644
index 000000000..74e99da15
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/error_reporter.ts
@@ -0,0 +1,40 @@
+import * as fs from 'fs';
+import * as express from 'express';
+import {utils} from './utils';
+import {configs} from './configs';
+import rollbar = require('rollbar');
+
+export const errorReporter = {
+ setup() {
+ rollbar.init(configs.ROLLBAR_ACCESS_KEY, {
+ environment: configs.ENVIRONMENT,
+ });
+
+ rollbar.handleUncaughtExceptions(configs.ROLLBAR_ACCESS_KEY);
+
+ process.on('unhandledRejection', (err: Error) => {
+ utils.consoleLog(`Uncaught exception ${err}. Stack: ${err.stack}`);
+ this.report(err);
+ process.exit(1);
+ });
+ },
+ reportAsync(err: Error, req?: express.Request): Promise<any> {
+ if (configs.ENVIRONMENT === 'development') {
+ return; // Do not log development environment errors
+ }
+
+ return new Promise((resolve, reject) => {
+ rollbar.handleError(err, req, (rollbarErr: Error) => {
+ if (rollbarErr) {
+ utils.consoleLog(`Error reporting to rollbar, ignoring: ${rollbarErr}`);
+ reject(rollbarErr);
+ } else {
+ resolve();
+ }
+ });
+ });
+ },
+ errorHandler() {
+ return rollbar.errorHandler(configs.ROLLBAR_ACCESS_KEY);
+ },
+};
diff --git a/packages/kovan-faucets/src/ts/ether_request_queue.ts b/packages/kovan-faucets/src/ts/ether_request_queue.ts
new file mode 100644
index 000000000..663f98082
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/ether_request_queue.ts
@@ -0,0 +1,26 @@
+import * as _ from 'lodash';
+import promisify = require('es6-promisify');
+import {utils} from './utils';
+import {configs} from './configs';
+import {RequestQueue} from './request_queue';
+import {errorReporter} from './error_reporter';
+
+const DISPENSE_AMOUNT_ETHER = 0.1;
+
+export class EtherRequestQueue extends RequestQueue {
+ protected async processNextRequestFireAndForgetAsync(recipientAddress: string) {
+ utils.consoleLog(`Processing ETH ${recipientAddress}`);
+ const sendTransactionAsync = promisify(this.web3.eth.sendTransaction);
+ try {
+ const txHash = await sendTransactionAsync({
+ from: configs.DISPENSER_ADDRESS,
+ to: recipientAddress,
+ value: this.web3.toWei(DISPENSE_AMOUNT_ETHER, 'ether'),
+ });
+ utils.consoleLog(`Sent ${DISPENSE_AMOUNT_ETHER} ETH to ${recipientAddress} tx: ${txHash}`);
+ } catch (err) {
+ utils.consoleLog(`Unexpected err: ${err} - ${JSON.stringify(err)}`);
+ await errorReporter.reportAsync(err);
+ }
+ }
+}
diff --git a/packages/kovan-faucets/src/ts/global.d.ts b/packages/kovan-faucets/src/ts/global.d.ts
new file mode 100644
index 000000000..cdfa67378
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/global.d.ts
@@ -0,0 +1,15 @@
+declare module 'elliptic';
+declare module 'rollbar';
+declare module 'ethereumjs-tx';
+declare module 'es6-promisify';
+declare module 'web3-provider-engine';
+declare module 'web3-provider-engine/subproviders/rpc';
+declare module 'web3-provider-engine/subproviders/nonce-tracker';
+declare module 'web3-provider-engine/subproviders/hooked-wallet';
+
+declare module '*.json' {
+ const json: any;
+ /* tslint:disable */
+ export default json;
+ /* tslint:enable */
+}
diff --git a/packages/kovan-faucets/src/ts/handler.ts b/packages/kovan-faucets/src/ts/handler.ts
new file mode 100644
index 000000000..460008e93
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/handler.ts
@@ -0,0 +1,88 @@
+import * as _ from 'lodash';
+import * as express from 'express';
+import {EtherRequestQueue} from './ether_request_queue';
+import {ZRXRequestQueue} from './zrx_request_queue';
+import {configs} from './configs';
+import {utils} from './utils';
+import ProviderEngine = require('web3-provider-engine');
+import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
+import NonceSubprovider = require('web3-provider-engine/subproviders/nonce-tracker');
+import HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet');
+import {idManagement} from './id_management';
+import * as Web3 from 'web3';
+// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
+// because they are using the wrong XHR package.
+// Issue: https://github.com/trufflesuite/truffle-contract/issues/14
+delete (global as any).XMLHttpRequest;
+
+export class Handler {
+ private etherRequestQueue: EtherRequestQueue;
+ private zrxRequestQueue: ZRXRequestQueue;
+ private web3: Web3;
+ constructor() {
+ // Setup provider engine to talk with RPC node
+ const providerObj = this.createProviderEngine(configs.RPC_URL);
+ this.web3 = new Web3(providerObj);
+
+ this.etherRequestQueue = new EtherRequestQueue(this.web3);
+ this.zrxRequestQueue = new ZRXRequestQueue(this.web3);
+ }
+ public dispenseEther(req: express.Request, res: express.Response) {
+ const recipientAddress = req.params.recipient;
+ if (_.isUndefined(recipientAddress) || !this.isValidEthereumAddress(recipientAddress)) {
+ res.status(400).send('INVALID_REQUEST');
+ return;
+ }
+ const lowerCaseRecipientAddress = recipientAddress.toLowerCase();
+ const didAddToQueue = this.etherRequestQueue.add(lowerCaseRecipientAddress);
+ if (!didAddToQueue) {
+ res.status(503).send('QUEUE_IS_FULL');
+ return;
+ }
+ utils.consoleLog(`Added ${lowerCaseRecipientAddress} to the ETH queue`);
+ res.status(200).end();
+ }
+ public dispenseZRX(req: express.Request, res: express.Response) {
+ const recipientAddress = req.params.recipient;
+ if (_.isUndefined(recipientAddress) || !this.isValidEthereumAddress(recipientAddress)) {
+ res.status(400).send('INVALID_REQUEST');
+ return;
+ }
+ const lowerCaseRecipientAddress = recipientAddress.toLowerCase();
+ const didAddToQueue = this.zrxRequestQueue.add(lowerCaseRecipientAddress);
+ if (!didAddToQueue) {
+ res.status(503).send('QUEUE_IS_FULL');
+ return;
+ }
+ utils.consoleLog(`Added ${lowerCaseRecipientAddress} to the ZRX queue`);
+ res.status(200).end();
+ }
+ public getQueueInfo(req: express.Request, res: express.Response) {
+ res.setHeader('Content-Type', 'application/json');
+ const payload = JSON.stringify({
+ ether: {
+ full: this.etherRequestQueue.isFull(),
+ size: this.etherRequestQueue.size(),
+ },
+ zrx: {
+ full: this.zrxRequestQueue.isFull(),
+ size: this.zrxRequestQueue.size(),
+ },
+ });
+ res.status(200).send(payload);
+ }
+ private createProviderEngine(rpcUrl: string) {
+ const engine = new ProviderEngine();
+ engine.addProvider(new NonceSubprovider());
+ engine.addProvider(new HookedWalletSubprovider(idManagement));
+ engine.addProvider(new RpcSubprovider({
+ rpcUrl,
+ }));
+ engine.start();
+ return engine;
+ }
+ private isValidEthereumAddress(address: string): boolean {
+ const lowercaseAddress = address.toLowerCase();
+ return this.web3.isAddress(lowercaseAddress);
+ }
+}
diff --git a/packages/kovan-faucets/src/ts/id_management.ts b/packages/kovan-faucets/src/ts/id_management.ts
new file mode 100644
index 000000000..838650be0
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/id_management.ts
@@ -0,0 +1,27 @@
+import {configs} from './configs';
+import * as EthereumTx from 'ethereumjs-tx';
+
+type Callback = (err: Error, accounts: any) => void;
+
+export const idManagement = {
+ getAccounts(callback: Callback) {
+ /* tslint:disable */
+ console.log('configs.DISPENSER_ADDRESS', configs.DISPENSER_ADDRESS);
+ /* tslint:enable */
+ callback(null, [
+ configs.DISPENSER_ADDRESS,
+ ]);
+ },
+ approveTransaction(txData: object, callback: Callback) {
+ callback(null, true);
+ },
+ signTransaction(txData: object, callback: Callback) {
+ /* tslint:disable */
+ let tx = new EthereumTx(txData);
+ /* tslint:enable */
+ const privateKeyBuffer = new Buffer(configs.DISPENSER_PRIVATE_KEY, 'hex');
+ tx.sign(privateKeyBuffer);
+ const rawTx = `0x${tx.serialize().toString('hex')}`;
+ callback(null, rawTx);
+ },
+};
diff --git a/packages/kovan-faucets/src/ts/request_queue.ts b/packages/kovan-faucets/src/ts/request_queue.ts
new file mode 100644
index 000000000..301aec8d5
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/request_queue.ts
@@ -0,0 +1,53 @@
+import * as _ from 'lodash';
+import * as timers from 'timers';
+import * as Web3 from 'web3';
+// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
+// because they are using the wrong XHR package.
+// Issue: https://github.com/trufflesuite/truffle-contract/issues/14
+delete (global as any).XMLHttpRequest;
+
+const MAX_QUEUE_SIZE = 500;
+const DEFAULT_QUEUE_INTERVAL_MS = 1000;
+
+export class RequestQueue {
+ protected queueIntervalMs: number;
+ protected queue: string[];
+ protected queueIntervalId: NodeJS.Timer;
+ protected web3: Web3;
+ constructor(web3: any) {
+ this.queueIntervalMs = DEFAULT_QUEUE_INTERVAL_MS;
+ this.queue = [];
+
+ this.web3 = web3;
+
+ this.start();
+ }
+ public add(recipientAddress: string): boolean {
+ if (this.isFull()) {
+ return false;
+ }
+ this.queue.push(recipientAddress);
+ return true;
+ }
+ public size(): number {
+ return this.queue.length;
+ }
+ public isFull(): boolean {
+ return this.size() >= MAX_QUEUE_SIZE;
+ }
+ protected start() {
+ this.queueIntervalId = timers.setInterval(() => {
+ if (this.queue.length === 0) {
+ return;
+ }
+ const recipientAddress = this.queue.shift();
+ this.processNextRequestFireAndForgetAsync(recipientAddress);
+ }, this.queueIntervalMs);
+ }
+ protected stop() {
+ clearInterval(this.queueIntervalId);
+ }
+ protected async processNextRequestFireAndForgetAsync(recipientAddress: string) {
+ throw new Error('Expected processNextRequestFireAndForgetAsync to be implemented by a superclass');
+ }
+}
diff --git a/packages/kovan-faucets/src/ts/server.ts b/packages/kovan-faucets/src/ts/server.ts
new file mode 100644
index 000000000..0ae10e556
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/server.ts
@@ -0,0 +1,27 @@
+import * as bodyParser from 'body-parser';
+import * as express from 'express';
+import {Handler} from './handler';
+import {errorReporter} from './error_reporter';
+
+// Setup the errorReporter to catch uncaught exceptions and unhandled rejections
+errorReporter.setup();
+
+const app = express();
+app.use(bodyParser.json()); // for parsing application/json
+app.use((req, res, next) => {
+ res.header('Access-Control-Allow-Origin', '*');
+ res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
+ next();
+});
+
+const handler = new Handler();
+app.get('/ping', (req: express.Request, res: express.Response) => { res.status(200).send('pong'); });
+app.get('/rain/:recipient', handler.dispenseEther.bind(handler)); // Deprecated gracefully
+app.get('/ether/:recipient', handler.dispenseEther.bind(handler));
+app.get('/zrx/:recipient', handler.dispenseZRX.bind(handler));
+app.get('/queue', handler.getQueueInfo.bind(handler)); // Deprecated gracefully
+
+// Log to rollbar any errors unhandled by handlers
+app.use(errorReporter.errorHandler());
+const port = process.env.PORT || 3000;
+app.listen(port);
diff --git a/packages/kovan-faucets/src/ts/utils.ts b/packages/kovan-faucets/src/ts/utils.ts
new file mode 100644
index 000000000..fd9630b76
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/utils.ts
@@ -0,0 +1,10 @@
+import * as _ from 'lodash';
+import * as express from 'express';
+
+export const utils = {
+ consoleLog(message: string) {
+ /* tslint:disable */
+ console.log(message);
+ /* tslint:enable */
+ },
+};
diff --git a/packages/kovan-faucets/src/ts/zrx_request_queue.ts b/packages/kovan-faucets/src/ts/zrx_request_queue.ts
new file mode 100644
index 000000000..e66a2b300
--- /dev/null
+++ b/packages/kovan-faucets/src/ts/zrx_request_queue.ts
@@ -0,0 +1,38 @@
+import * as _ from 'lodash';
+import {ZeroEx} from '0x.js';
+import BigNumber from 'bignumber.js';
+import promisify = require('es6-promisify');
+import {utils} from './utils';
+import {configs} from './configs';
+import {RequestQueue} from './request_queue';
+import {errorReporter} from './error_reporter';
+import * as Web3 from 'web3';
+// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
+// because they are using the wrong XHR package.
+// Issue: https://github.com/trufflesuite/truffle-contract/issues/14
+delete (global as any).XMLHttpRequest;
+
+const DISPENSE_AMOUNT_ZRX = new BigNumber(0.1);
+const QUEUE_INTERVAL_MS = 5000;
+
+export class ZRXRequestQueue extends RequestQueue {
+ private zeroEx: ZeroEx;
+ constructor(web3: Web3) {
+ super(web3);
+ this.queueIntervalMs = QUEUE_INTERVAL_MS;
+ this.zeroEx = new ZeroEx(web3.currentProvider);
+ }
+ protected async processNextRequestFireAndForgetAsync(recipientAddress: string) {
+ utils.consoleLog(`Processing ZRX ${recipientAddress}`);
+ const baseUnitAmount = ZeroEx.toBaseUnitAmount(DISPENSE_AMOUNT_ZRX, 18);
+ try {
+ await this.zeroEx.token.transferAsync(
+ configs.ZRX_TOKEN_ADDRESS, configs.DISPENSER_ADDRESS, recipientAddress, baseUnitAmount,
+ );
+ utils.consoleLog(`Sent ${DISPENSE_AMOUNT_ZRX} ZRX to ${recipientAddress}`);
+ } catch (err) {
+ utils.consoleLog(`Unexpected err: ${err} - ${JSON.stringify(err)}`);
+ await errorReporter.reportAsync(err);
+ }
+ }
+}
diff --git a/packages/kovan-faucets/tsconfig.json b/packages/kovan-faucets/tsconfig.json
new file mode 100644
index 000000000..4e995704a
--- /dev/null
+++ b/packages/kovan-faucets/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "compilerOptions": {
+ "outDir": "./transpiled/",
+ "sourceMap": true,
+ "noImplicitAny": true,
+ "module": "commonjs",
+ "target": "es5",
+ "baseUrl": "./src/",
+ "types": [ "body-parser", "es6-promise", "express", "lodash" ]
+ },
+ "include": [
+ "../../node_modules/web3-typescript-typings/index.d.ts",
+ "./src/ts/**/*"
+ ]
+}
diff --git a/packages/kovan-faucets/tslint.json b/packages/kovan-faucets/tslint.json
new file mode 100644
index 000000000..a07795151
--- /dev/null
+++ b/packages/kovan-faucets/tslint.json
@@ -0,0 +1,5 @@
+{
+ "extends": [
+ "@0xproject/tslint-config"
+ ]
+}
diff --git a/yarn.lock b/yarn.lock
index d795b1300..399c8a8ec 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -360,6 +360,12 @@ amdefine@>=0.0.4:
version "1.0.1"
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+ansi-align@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
+ dependencies:
+ string-width "^2.0.0"
+
ansi-escapes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
@@ -442,6 +448,14 @@ arr-union@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
+array-differ@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031"
+
+array-each@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f"
+
array-filter@~0.0.0:
version "0.0.1"
resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec"
@@ -477,13 +491,17 @@ array-reduce@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b"
+array-slice@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.0.0.tgz#e73034f00dcc1f40876008fd20feae77bd4b7c2f"
+
array-union@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
dependencies:
array-uniq "^1.0.1"
-array-uniq@^1.0.0, array-uniq@^1.0.1:
+array-uniq@^1.0.0, array-uniq@^1.0.1, array-uniq@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
@@ -579,6 +597,10 @@ async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0:
dependencies:
lodash "^4.14.0"
+async@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/async/-/async-1.2.1.tgz#a4816a17cd5ff516dfa2c7698a453369b9790de0"
+
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -1254,6 +1276,10 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
+beeper@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809"
+
big.js@^3.1.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
@@ -1599,7 +1625,7 @@ camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
-camelcase@^4.1.0:
+camelcase@^4.0.0, camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
@@ -1782,7 +1808,15 @@ cliui@^3.2.0:
strip-ansi "^3.0.1"
wrap-ansi "^2.0.0"
-clone@^1.0.2:
+clone-stats@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1"
+
+clone@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f"
+
+clone@^1.0.0, clone@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f"
@@ -2480,7 +2514,7 @@ debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
- ms "2.0.0"
+ find "^0.2.4"
debug@3.1.0, debug@^3.1.0:
version "3.1.0"
@@ -2530,7 +2564,7 @@ default-require-extensions@^1.0.0:
dependencies:
strip-bom "^2.0.0"
-defaults@^1.0.3:
+defaults@^1.0.0, defaults@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
dependencies:
@@ -2688,6 +2722,12 @@ dot-prop@^3.0.0:
dependencies:
is-obj "^1.0.0"
+dot-prop@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
+ dependencies:
+ is-obj "^1.0.0"
+
drbg.js@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b"
@@ -2696,7 +2736,7 @@ drbg.js@^1.0.1:
create-hash "^1.1.2"
create-hmac "^1.1.4"
-duplexer2@~0.0.2:
+duplexer2@0.0.2, duplexer2@~0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db"
dependencies:
@@ -2764,6 +2804,12 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
+end-of-stream@~0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf"
+ dependencies:
+ once "~1.3.0"
+
enhanced-resolve@3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.3.0.tgz#950964ecc7f0332a42321b673b38dc8ff15535b3"
@@ -2846,6 +2892,10 @@ es6-object-assign@^1.0.3:
version "1.1.0"
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
+es6-promise@^3.3.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
+
es6-promise@^4.0.3:
version "4.1.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a"
@@ -3246,7 +3296,7 @@ extend-shallow@^2.0.1:
dependencies:
is-extendable "^0.1.0"
-extend@~3.0.0, extend@~3.0.1:
+extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
@@ -3287,6 +3337,13 @@ fake-merkle-patricia-tree@^1.0.1:
dependencies:
checkpoint-store "^1.1.0"
+fancy-log@^1.1.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948"
+ dependencies:
+ chalk "^1.1.1"
+ time-stamp "^1.0.0"
+
fast-deep-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
@@ -3397,6 +3454,10 @@ find-cache-dir@^0.1.1:
mkdirp "^0.5.1"
pkg-dir "^1.0.0"
+find-index@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4"
+
find-up@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
@@ -3437,6 +3498,12 @@ for-own@^0.1.4:
dependencies:
for-in "^1.0.1"
+for-own@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b"
+ dependencies:
+ for-in "^1.0.1"
+
foreach@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
@@ -3492,6 +3559,10 @@ from@~0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
+fs-exists-sync@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
+
fs-extra@^0.30.0:
version "0.30.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
@@ -3559,6 +3630,12 @@ gauge@~2.7.3:
strip-ansi "^3.0.1"
wide-align "^1.1.0"
+gaze@^0.5.1:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f"
+ dependencies:
+ globule "~0.1.0"
+
get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
@@ -3673,6 +3750,17 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
+glob-stream@^3.1.5:
+ version "3.1.18"
+ resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b"
+ dependencies:
+ glob "^4.3.1"
+ glob2base "^0.0.12"
+ minimatch "^2.0.1"
+ ordered-read-streams "^0.1.0"
+ through2 "^0.6.1"
+ unique-stream "^1.0.0"
+
glob-to-regexp@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
@@ -3727,6 +3815,20 @@ globby@^6.1.0:
pify "^2.0.0"
pinkie-promise "^2.0.0"
+globule@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5"
+ dependencies:
+ glob "~3.1.21"
+ lodash "~1.0.1"
+ minimatch "~0.2.11"
+
+glogg@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5"
+ dependencies:
+ sparkles "^1.0.0"
+
got@^6.7.1:
version "6.7.1"
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
@@ -3743,6 +3845,12 @@ got@^6.7.1:
unzip-response "^2.0.1"
url-parse-lax "^1.0.0"
+graceful-fs@^3.0.0:
+ version "3.0.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818"
+ dependencies:
+ natives "^1.1.0"
+
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
@@ -3809,6 +3917,12 @@ has-flag@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
+has-gulplog@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce"
+ dependencies:
+ sparkles "^1.0.0"
+
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -3940,6 +4054,12 @@ home-or-tmp@^2.0.0:
os-homedir "^1.0.0"
os-tmpdir "^1.0.1"
+homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc"
+ dependencies:
+ parse-passwd "^1.0.0"
+
hosted-git-info@^2.1.4, hosted-git-info@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
@@ -4104,7 +4224,7 @@ inherits@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
-ini@^1.3.2, ini@~1.3.0:
+ini@^1.3.2, ini@^1.3.4, ini@~1.3.0:
version "1.3.4"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
@@ -4383,6 +4503,12 @@ is-regex@^1.0.4:
dependencies:
has "^1.0.1"
+is-relative@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5"
+ dependencies:
+ is-unc-path "^0.1.1"
+
is-retry-allowed@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
@@ -4415,6 +4541,12 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+is-unc-path@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9"
+ dependencies:
+ unc-path-regex "^0.1.0"
+
is-url@^1.1.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.2.tgz#498905a593bf47cc2d9e7f738372bbf7696c7f26"
@@ -4600,7 +4732,7 @@ json-stable-stringify@^1.0.1:
dependencies:
jsonify "~0.0.0"
-json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
+json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.0, json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
@@ -4704,6 +4836,12 @@ klaw@^1.0.0:
optionalDependencies:
graceful-fs "^4.1.9"
+latest-version@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
+ dependencies:
+ package-json "^4.0.0"
+
lazy-cache@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
@@ -4832,6 +4970,20 @@ levelup@^1.2.1:
semver "~5.4.1"
xtend "~4.0.0"
+liftoff@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.3.0.tgz#a98f2ff67183d8ba7cfaca10548bd7ff0550b385"
+ dependencies:
+ extend "^3.0.0"
+ findup-sync "^0.4.2"
+ fined "^1.0.1"
+ flagged-respawn "^0.3.2"
+ lodash.isplainobject "^4.0.4"
+ lodash.isstring "^4.0.1"
+ lodash.mapvalues "^4.4.0"
+ rechoir "^0.6.2"
+ resolve "^1.1.7"
+
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -4890,6 +5042,15 @@ loader-utils@^1.0.2, loader-utils@^1.1.0:
emojis-list "^2.0.0"
json5 "^0.5.0"
+loader-utils@~0.2.2:
+ version "0.2.17"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
+ dependencies:
+ big.js "^3.1.3"
+ emojis-list "^2.0.0"
+ json5 "^0.5.0"
+ object-assign "^4.0.1"
+
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@@ -5006,6 +5167,13 @@ lodash.template@^4.0.2:
lodash._reinterpolate "~3.0.0"
lodash.templatesettings "^4.0.0"
+lodash.templatesettings@^3.0.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5"
+ dependencies:
+ lodash._reinterpolate "^3.0.0"
+ lodash.escape "^3.0.0"
+
lodash.templatesettings@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316"
@@ -5038,6 +5206,10 @@ lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.2, lo
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+lodash@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551"
+
log-driver@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056"
@@ -5086,6 +5258,10 @@ lru-cache@^4.0.1:
pseudomap "^1.0.2"
yallist "^2.1.2"
+lru-cache@~2.2.1:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d"
+
ltcdr@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ltcdr/-/ltcdr-2.2.1.tgz#5ab87ad1d4c1dab8e8c08bbf037ee0c1902287cf"
@@ -5104,7 +5280,7 @@ make-dir@^1.0.0:
dependencies:
pify "^3.0.0"
-map-cache@^0.2.2:
+map-cache@^0.2.0, map-cache@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
@@ -5334,6 +5510,13 @@ minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
dependencies:
brace-expansion "^1.1.7"
+minimatch@~0.2.11:
+ version "0.2.14"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a"
+ dependencies:
+ lru-cache "2"
+ sigmund "~1.0.0"
+
minimist@0.0.8, minimist@~0.0.1:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@@ -5342,7 +5525,7 @@ minimist@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de"
-minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@~1.2.0:
+minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
@@ -5562,6 +5745,21 @@ node-pre-gyp@^0.6.39:
tar "^2.2.1"
tar-pack "^3.4.0"
+nodemon@^1.11.0:
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.12.1.tgz#996a56dc49d9f16bbf1b78a4de08f13634b3878d"
+ dependencies:
+ chokidar "^1.7.0"
+ debug "^2.6.8"
+ es6-promise "^3.3.1"
+ ignore-by-default "^1.0.1"
+ lodash.defaults "^3.1.2"
+ minimatch "^3.0.4"
+ ps-tree "^1.1.0"
+ touch "^3.1.0"
+ undefsafe "0.0.3"
+ update-notifier "^2.2.0"
+
noms@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859"
@@ -5732,6 +5930,15 @@ object-visit@^1.0.0:
dependencies:
isobject "^3.0.0"
+object.defaults@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf"
+ dependencies:
+ array-each "^1.0.1"
+ array-slice "^1.0.0"
+ for-own "^1.0.0"
+ isobject "^3.0.0"
+
object.omit@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
@@ -5739,7 +5946,7 @@ object.omit@^2.0.0:
for-own "^0.1.4"
is-extendable "^0.1.1"
-object.pick@^1.3.0:
+object.pick@^1.2.0, object.pick@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
dependencies:
@@ -5891,6 +6098,14 @@ parse-asn1@^5.0.0:
evp_bytestokey "^1.0.0"
pbkdf2 "^3.0.3"
+parse-filepath@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.1.tgz#159d6155d43904d16c10ef698911da1e91969b73"
+ dependencies:
+ is-absolute "^0.2.3"
+ map-cache "^0.2.0"
+ path-root "^0.1.1"
+
parse-github-repo-url@^1.3.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50"
@@ -6360,6 +6575,10 @@ pretty-bytes@^1.0.4:
get-stdin "^4.0.1"
meow "^3.1.0"
+pretty-hrtime@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
+
private@^0.1.6, private@^0.1.7:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
@@ -7037,6 +7256,14 @@ repeating@^2.0.0:
dependencies:
is-finite "^1.0.0"
+replace-ext@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924"
+
+request-ip@~1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/request-ip/-/request-ip-1.2.3.tgz#66988f0e22406ec4af630d19b573fe4b447c3b49"
+
request-promise-core@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6"
@@ -7131,6 +7358,13 @@ resolve-cwd@^2.0.0:
dependencies:
resolve-from "^3.0.0"
+resolve-dir@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e"
+ dependencies:
+ expand-tilde "^1.2.2"
+ global-modules "^0.2.3"
+
resolve-from@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
@@ -7153,6 +7387,12 @@ resolve@^1.1.6, resolve@^1.3.2, resolve@~1.4.0:
dependencies:
path-parse "^1.0.5"
+resolve@^1.1.7:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
+ dependencies:
+ path-parse "^1.0.5"
+
restore-cursor@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
@@ -7195,6 +7435,19 @@ rlp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.0.0.tgz#9db384ff4b89a8f61563d92395d8625b18f3afb0"
+rollbar@^0.6.5:
+ version "0.6.6"
+ resolved "https://registry.yarnpkg.com/rollbar/-/rollbar-0.6.6.tgz#8630cff4af967667d06b227f243635ea86dcc5ba"
+ dependencies:
+ async "~1.2.1"
+ debug "2.2.0"
+ json-stringify-safe "~5.0.0"
+ lru-cache "~2.2.1"
+ request-ip "~1.2.3"
+ uuid "~3.0.0"
+ optionalDependencies:
+ decache "^3.0.5"
+
run-async@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
@@ -7295,6 +7548,12 @@ semaphore@>=1.0.1, semaphore@^1.0.3:
version "1.1.0"
resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa"
+semver-diff@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
+ dependencies:
+ semver "^5.0.3"
+
semver-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9"
@@ -7650,6 +7909,10 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+sparkles@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3"
+
spawn-wrap@=1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.8.tgz#fa2a79b990cbb0bb0018dca6748d88367b19ec31"
@@ -7776,6 +8039,10 @@ stream-combiner@~0.0.4:
dependencies:
duplexer "~0.1.1"
+stream-consume@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f"
+
stream-http@^2.3.1:
version "2.7.2"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad"
@@ -7863,6 +8130,13 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
+strip-bom@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794"
+ dependencies:
+ first-chunk-stream "^1.0.0"
+ is-utf8 "^0.2.0"
+
strip-bom@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
@@ -8078,6 +8352,12 @@ tempfile@^1.1.1:
os-tmpdir "^1.0.0"
uuid "^2.0.1"
+term-size@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
+ dependencies:
+ execa "^0.7.0"
+
test-exclude@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26"
@@ -8114,13 +8394,6 @@ through2@~0.2.3:
readable-stream "~1.1.9"
xtend "~2.1.1"
-through2@~0.6.3:
- version "0.6.5"
- resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48"
- dependencies:
- readable-stream ">=1.0.33-1 <1.1.0-0"
- xtend ">=4.0.0 <4.1.0-0"
-
through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
@@ -8208,6 +8481,10 @@ tough-cookie@>=2.3.3, tough-cookie@~2.3.0, tough-cookie@~2.3.3:
dependencies:
punycode "^1.4.1"
+traverse-chain@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1"
+
trim-newlines@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
@@ -8478,6 +8755,20 @@ unzip-response@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
+update-notifier@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451"
+ dependencies:
+ boxen "^1.2.1"
+ chalk "^2.0.1"
+ configstore "^3.0.0"
+ import-lazy "^2.1.0"
+ is-installed-globally "^0.1.0"
+ is-npm "^1.0.0"
+ latest-version "^3.0.0"
+ semver-diff "^2.0.0"
+ xdg-basedir "^3.0.0"
+
urix@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
@@ -8567,6 +8858,12 @@ uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
+v8flags@^2.0.2:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
+ dependencies:
+ user-home "^1.1.1"
+
valid-url@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
@@ -8598,6 +8895,34 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
+vinyl-fs@^0.3.0:
+ version "0.3.14"
+ resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6"
+ dependencies:
+ defaults "^1.0.0"
+ glob-stream "^3.1.5"
+ glob-watcher "^0.0.6"
+ graceful-fs "^3.0.0"
+ mkdirp "^0.5.0"
+ strip-bom "^1.0.0"
+ through2 "^0.6.1"
+ vinyl "^0.4.0"
+
+vinyl@^0.4.0:
+ version "0.4.6"
+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
+ dependencies:
+ clone "^0.2.0"
+ clone-stats "^0.0.1"
+
+vinyl@^0.5.0:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde"
+ dependencies:
+ clone "^1.0.0"
+ clone-stats "^0.0.1"
+ replace-ext "0.0.1"
+
vm-browserify@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
@@ -8856,7 +9181,7 @@ which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
-which@^1.2.4, which@^1.2.9:
+which@^1.2.12, which@^1.2.4, which@^1.2.9:
version "1.3.0"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
dependencies:
@@ -8868,6 +9193,12 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2"
+widest-line@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c"
+ dependencies:
+ string-width "^1.0.1"
+
window-size@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"