From 5f3498eaf51dbd0e6d7d24519c499d753bc7a918 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Fri, 21 Jun 2019 12:38:45 -0300 Subject: [PATCH 01/20] Refactors delegate helper as a service to improve testing --- package-lock.json | 139 ++++++++++++++++++-- package.json | 1 + server/delegate/delegate.controller.js | 16 +-- server/helpers/delegate.js | 173 +++++++++++++------------ test/server/helpers/delegate.test.js | 24 +++- 5 files changed, 245 insertions(+), 108 deletions(-) diff --git a/package-lock.json b/package-lock.json index add76fe..592e202 100644 --- a/package-lock.json +++ b/package-lock.json @@ -286,6 +286,38 @@ "@sendgrid/helpers": "^6.3.0" } }, + "@sinonjs/commons": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", + "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", + "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", + "requires": { + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash": "^4.17.11" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" + }, "@types/caseless": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz", @@ -591,6 +623,11 @@ "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" + }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -1728,8 +1765,7 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, "dns-prefetch-control": { "version": "0.1.0", @@ -3112,7 +3148,8 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true }, "aproba": { "version": "1.2.0", @@ -3155,7 +3192,8 @@ "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=" + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true }, "concat-map": { "version": "0.0.1", @@ -3166,7 +3204,8 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -3283,7 +3322,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "optional": true }, "ini": { "version": "1.3.5", @@ -3295,6 +3335,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3324,6 +3365,7 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3342,6 +3384,7 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "optional": true, "requires": { "minimist": "0.0.8" } @@ -3428,7 +3471,8 @@ "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=" + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3440,6 +3484,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, "requires": { "wrappy": "1" } @@ -3525,7 +3570,8 @@ "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==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3561,6 +3607,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3580,6 +3627,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3623,12 +3671,14 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "optional": true } } }, @@ -4710,6 +4760,11 @@ "verror": "1.10.0" } }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==" + }, "kareem": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.0.tgz", @@ -4860,6 +4915,11 @@ "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", "dev": true }, + "lolex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz", + "integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==" + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -5312,6 +5372,33 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "nise": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz", + "integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==", + "requires": { + "@sinonjs/formatio": "^3.1.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^4.1.0", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + } + } + } + }, "nocache": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz", @@ -6390,6 +6477,35 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "sinon": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.3.2.tgz", + "integrity": "sha512-thErC1z64BeyGiPvF8aoSg0LEnptSaWE7YhdWWbWXgelOyThent7uKOnnEh9zBxDbKixtr5dEko+ws1sZMuFMA==", + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.1", + "diff": "^3.5.0", + "lolex": "^4.0.1", + "nise": "^1.4.10", + "supports-color": "^5.5.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "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" + } + } + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -7034,8 +7150,7 @@ "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 + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-is": { "version": "1.6.16", diff --git a/package.json b/package.json index 9f9ae7c..8355c67 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "node-telegram-bot-api": "^0.30.0", "nodemon": "^1.19.1", "promise-retry": "^1.1.1", + "sinon": "^7.3.2", "striptags": "^3.1.1", "web3": "github:ethereum/web3.js", "winston": "2.4.1" diff --git a/server/delegate/delegate.controller.js b/server/delegate/delegate.controller.js index 4ac0143..0ce4446 100644 --- a/server/delegate/delegate.controller.js +++ b/server/delegate/delegate.controller.js @@ -1,18 +1,17 @@ /** - * Activate subscriber. - * @returns {Subscriber} + * Handler for delegates + * @returns {Delegate} */ -const { getDelegate } = require('../helpers/delegate') - const { MathBN, tokenAmountInUnits } = require('../helpers/utils') const BN = require('bn.js') -const { getDelegateRewards, getDelegateTotalStake } = require('../helpers/graphql/queries/delegate') +const { getDelegateService } = require('../helpers/delegate') const getByAddress = async (req, res, next) => { const { address } = req.params + const delegateService = getDelegateService() try { - const result = await getDelegate(address) + const result = await delegateService.getDelegate(address) res.json(result) } catch (error) { next(error) @@ -20,9 +19,10 @@ const getByAddress = async (req, res, next) => { } const getROI = async (req, res, next) => { const { address } = req.params + const delegateService = getDelegateService() try { - const rewards = await getDelegateRewards(address) - const totalStake = await getDelegateTotalStake(address) + const rewards = await delegateService.getDelegateRewards(address) + const totalStake = await delegateService.getDelegateTotalStake(address) let roi = null if (rewards && totalStake) { const totalReward = rewards.reduce((total, reward) => { diff --git a/server/helpers/delegate.js b/server/helpers/delegate.js index 55dce24..a8cd56c 100644 --- a/server/helpers/delegate.js +++ b/server/helpers/delegate.js @@ -1,5 +1,4 @@ const _ = require('lodash') - const { tokenAmountInUnits } = require('./utils') const { PROTOCOL_DIVISION_BASE } = require('../../config/constants') @@ -8,99 +7,111 @@ const { calculateMissedRewardCalls } = require('./utils') const { getCurrentRound } = require('./graphql/queries/protocol') -const { - getMintedTokensForNextRound, - getLivepeerDelegatorAccount, - getTotalBonded -} = require('./livepeerAPI') +let delegateServiceInstance +const defaultDelegateSource = require('./graphql/queries/delegate') +const defaultProtocolSource = require('./livepeerAPI') + +const getDelegateService = ( + delegateSource = defaultDelegateSource, + protocolSource = defaultProtocolSource +) => { + if (!delegateServiceInstance) { + delegateServiceInstance = new DelegateService(delegateSource, protocolSource) + } + return delegateServiceInstance +} -const { - getDelegateSummary, - getDelegateTotalStake, - getDelegateRewards -} = require('./graphql/queries/delegate') +class DelegateService { + constructor(delegateDataSource, protocolDataSource) { + this.delegateSource = delegateDataSource + this.protocolSource = protocolDataSource + } -// Returns the delegate summary plus the missed reward calls -const getDelegate = async delegateAddress => { - const summary = await getDelegateSummary(delegateAddress) - const last30MissedRewardCalls = await getMissedRewardCalls(delegateAddress) - return { - summary: { - ...summary, - totalStake: tokenAmountInUnits(_.get(summary, 'totalStake', 0)), - last30MissedRewardCalls + // Returns the delegate summary plus the missed reward calls + async getDelegate(delegateAddress) { + const { getDelegateSummary } = this.delegateSource + const summary = await getDelegateSummary(delegateAddress) + const last30MissedRewardCalls = await this.getMissedRewardCalls(delegateAddress) + return { + summary: { + ...summary, + totalStake: tokenAmountInUnits(_.get(summary, 'totalStake', 0)), + last30MissedRewardCalls + } } } -} -// Receives a delegateAddress and returns the TOTAL reward (protocol reward, no the reward cut) of that delegate for the next round -const getDelegateProtocolNextReward = async delegateAddress => { - // FORMULA: mintedTokensForNextRound * delegateParticipationInTotalBonded - let [summary, mintedTokensForNextRound, totalBondedInProtocol] = await Promise.all([ - getDelegateSummary(delegateAddress), - getMintedTokensForNextRound(), - getTotalBonded() - ]) - const { totalStake } = summary - // FORMULA: delegateTotalStake / protocolTotalBonded - const participationInTotalBondedRatio = MathBN.div(totalStake, totalBondedInProtocol) + // Receives a delegateAddress and returns the TOTAL reward (protocol reward, no the reward cut) of that delegate for the next round + async getDelegateProtocolNextReward(delegateAddress) { + const { getDelegateSummary } = this.delegateSource + const { getMintedTokensForNextRound, getTotalBonded } = this.protocolSource + // FORMULA: mintedTokensForNextRound * delegateParticipationInTotalBonded + let [summary, mintedTokensForNextRound, totalBondedInProtocol] = await Promise.all([ + getDelegateSummary(delegateAddress), + getMintedTokensForNextRound(), + getTotalBonded() + ]) + const { totalStake } = summary + // FORMULA: delegateTotalStake / protocolTotalBonded + const participationInTotalBondedRatio = MathBN.div(totalStake, totalBondedInProtocol) - return MathBN.mul(mintedTokensForNextRound, participationInTotalBondedRatio) -} + return MathBN.mul(mintedTokensForNextRound, participationInTotalBondedRatio) + } -// Receives a delegateAddress and returns the REAL reward of the delegate (nextReward*rewardCut) -const getDelegateNextReward = async delegateAddress => { - // DelegateReward = DelegateProtocolNextReward * rewardCut - let [summary, protocolNextReward] = await Promise.all([ - getDelegateSummary(delegateAddress), - getDelegateProtocolNextReward(delegateAddress) - ]) - const { pendingRewardCut } = summary - const rewardCut = MathBN.div(pendingRewardCut, PROTOCOL_DIVISION_BASE) - return MathBN.mul(protocolNextReward, rewardCut) -} + // Receives a delegateAddress and returns the REAL reward of the delegate (nextReward*rewardCut) + async getDelegateNextReward(delegateAddress) { + const { getDelegateSummary, getDelegateProtocolNextReward } = this.delegateSource + // DelegateReward = DelegateProtocolNextReward * rewardCut + let [summary, protocolNextReward] = await Promise.all([ + getDelegateSummary(delegateAddress), + getDelegateProtocolNextReward(delegateAddress) + ]) + const { pendingRewardCut } = summary + const rewardCut = MathBN.div(pendingRewardCut, PROTOCOL_DIVISION_BASE) + return MathBN.mul(protocolNextReward, rewardCut) + } -// For a given delegateAddress return the next reward that will be distributed towards delegators -const getDelegateRewardToDelegators = async delegateAddress => { - // FORMULA: DelegateRewardToDelegators = DelegateProtocolNextReward - DelegateProtocolNextReward * rewardCut - let [summary, protocolNextReward] = await Promise.all([ - getDelegateSummary(delegateAddress), - getDelegateProtocolNextReward(delegateAddress) - ]) - const { pendingRewardCut } = summary - const rewardCut = MathBN.div(pendingRewardCut, PROTOCOL_DIVISION_BASE) - const rewardToDelegate = MathBN.mul(protocolNextReward, rewardCut) - return MathBN.sub(protocolNextReward, rewardToDelegate) -} + // For a given delegateAddress return the next reward that will be distributed towards delegators + async getDelegateRewardToDelegators(delegateAddress) { + const { getDelegateSummary, getDelegateProtocolNextReward } = this.delegateSource + // FORMULA: DelegateRewardToDelegators = DelegateProtocolNextReward - DelegateProtocolNextReward * rewardCut + let [summary, protocolNextReward] = await Promise.all([ + getDelegateSummary(delegateAddress), + getDelegateProtocolNextReward(delegateAddress) + ]) + const { pendingRewardCut } = summary + const rewardCut = MathBN.div(pendingRewardCut, PROTOCOL_DIVISION_BASE) + const rewardToDelegate = MathBN.mul(protocolNextReward, rewardCut) + return MathBN.sub(protocolNextReward, rewardToDelegate) + } -// For a given delegatorAddress, returns the next round reward if exists -const getDelegatorNextReturn = async delegatorAddress => { - // FORMULA: rewardToDelegators * delegatorParticipationInTotalStake - const delegator = await getLivepeerDelegatorAccount(delegatorAddress) - const { delegateAddress, totalStake } = delegator - const delegateTotalStake = await getDelegateTotalStake(delegateAddress) - // FORMULA: delegateTotalStake / totalStake - const delegatorParticipationInTotalStake = MathBN.div(delegateTotalStake, totalStake) - const rewardToDelegators = await getDelegateRewardToDelegators(delegateAddress) - return MathBN.mul(rewardToDelegators, delegatorParticipationInTotalStake) -} + // For a given delegatorAddress, returns the next round reward if exists + async getDelegatorNextReturn(delegatorAddress) { + const { getLivepeerDelegatorAccount } = this.protocolSource + const { getDelegateTotalStake, getDelegateRewardToDelegators } = this.delegateSource + // FORMULA: rewardToDelegators * delegatorParticipationInTotalStake + const delegator = await getLivepeerDelegatorAccount(delegatorAddress) + const { delegateAddress, totalStake } = delegator + const delegateTotalStake = await getDelegateTotalStake(delegateAddress) + // FORMULA: delegateTotalStake / totalStake + const delegatorParticipationInTotalStake = MathBN.div(delegateTotalStake, totalStake) + const rewardToDelegators = await getDelegateRewardToDelegators(delegateAddress) + return MathBN.mul(rewardToDelegators, delegatorParticipationInTotalStake) + } -const getMissedRewardCalls = async delegateAddress => { - let missedCalls = 0 - const rewards = await getDelegateRewards(delegateAddress) - const currentRound = await getCurrentRound() + async getMissedRewardCalls(delegateAddress) { + const { getDelegateRewards } = this.delegateSource + let missedCalls = 0 + const rewards = await getDelegateRewards(delegateAddress) + const currentRound = await getCurrentRound() - if (rewards) { - missedCalls = calculateMissedRewardCalls(rewards, currentRound) + if (rewards) { + missedCalls = calculateMissedRewardCalls(rewards, currentRound) + } + return missedCalls } - return missedCalls } module.exports = { - getDelegate, - getDelegateProtocolNextReward, - getDelegateNextReward, - getDelegateRewardToDelegators, - getDelegatorNextReturn, - getMissedRewardCalls + getDelegateService } diff --git a/test/server/helpers/delegate.test.js b/test/server/helpers/delegate.test.js index 946217f..017ab81 100644 --- a/test/server/helpers/delegate.test.js +++ b/test/server/helpers/delegate.test.js @@ -1,14 +1,24 @@ -const { createRewardObject } = require('../server/helpers/test/util') -const BN = require('bn.js') -const { calculateMissedRewardCalls } = require('../server/helpers/utils') +const { getDelegate } = require('../../../server/helpers/delegate') + +const { createTranscoder } = require('../../../server/helpers/test/util') +let delegatesGrapqhl = require('../../../server/helpers/graphql/queries/delegate') const chai = require('chai') // eslint-disable-line import/newline-after-import -const expect = chai.expect +const jest = require('jest') +/*const expect = chai.expect const assert = chai.assert -const { MathBN } = require('../server/helpers/utils') - -chai.config.includeStack = true +const sinon = require('sinon')*/ describe('## Delegate test', () => { + describe('# getDelegate', () => { + it('There are 30 rounds, 10 of them do not have reward object, result should be 10', async () => { + // given + const delegate = createTranscoder() + // when + const result = await getDelegate() + console.log('Get delegate ', result) + // then + }) + }) describe('# getDelegateProtocolNextReward', () => { it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => {}) }) From 46b134572ec1f5371656669b8ef0a46084128580 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Fri, 21 Jun 2019 13:30:33 -0300 Subject: [PATCH 02/20] Adds test for getDelegate --- server/delegate/delegate.controller.js | 2 +- .../{delegate.js => delegateService.js} | 0 server/helpers/test/util.js | 14 ++++++- test/server/helpers/delegate.test.js | 40 ++++++++++++++----- 4 files changed, 42 insertions(+), 14 deletions(-) rename server/helpers/{delegate.js => delegateService.js} (100%) diff --git a/server/delegate/delegate.controller.js b/server/delegate/delegate.controller.js index 0ce4446..8f60dfe 100644 --- a/server/delegate/delegate.controller.js +++ b/server/delegate/delegate.controller.js @@ -5,7 +5,7 @@ const { MathBN, tokenAmountInUnits } = require('../helpers/utils') const BN = require('bn.js') -const { getDelegateService } = require('../helpers/delegate') +const { getDelegateService } = require('../helpers/delegateService') const getByAddress = async (req, res, next) => { const { address } = req.params diff --git a/server/helpers/delegate.js b/server/helpers/delegateService.js similarity index 100% rename from server/helpers/delegate.js rename to server/helpers/delegateService.js diff --git a/server/helpers/test/util.js b/server/helpers/test/util.js index d46642c..985be36 100644 --- a/server/helpers/test/util.js +++ b/server/helpers/test/util.js @@ -23,11 +23,21 @@ const createRoundObject = roundId => { // TODO Complete with all the fields const createTranscoder = transcoderId => { - return { + const mockTranscoder = { id: transcoderId, active: true, - status: 'Registered' + ensName: null, + status: 'Registered', + lastRewardRound: '1092', + rewardCut: '100000', + feeShare: '450000', + pricePerSegment: '150000000000', + pendingRewardCut: '50000', + pendingFeeShare: '450000', + pendingPricePerSegment: '150000000000', + totalStake: '440522208151278163711606' } + return mockTranscoder } module.exports = { diff --git a/test/server/helpers/delegate.test.js b/test/server/helpers/delegate.test.js index 017ab81..7d2d33c 100644 --- a/test/server/helpers/delegate.test.js +++ b/test/server/helpers/delegate.test.js @@ -1,22 +1,40 @@ -const { getDelegate } = require('../../../server/helpers/delegate') +const { tokenAmountInUnits } = require('../../../server/helpers/utils') + +const { getDelegateService } = require('../../../server/helpers/delegateService') const { createTranscoder } = require('../../../server/helpers/test/util') -let delegatesGrapqhl = require('../../../server/helpers/graphql/queries/delegate') -const chai = require('chai') // eslint-disable-line import/newline-after-import -const jest = require('jest') -/*const expect = chai.expect -const assert = chai.assert -const sinon = require('sinon')*/ +const delegatesGraphql = require('../../../server/helpers/graphql/queries/delegate') +const protocolSdk = require('../../../server/helpers/livepeerAPI') +const chai = require('chai') +const expect = chai.expect +const sinon = require('sinon') -describe('## Delegate test', () => { +describe('## DelegateService test', () => { describe('# getDelegate', () => { - it('There are 30 rounds, 10 of them do not have reward object, result should be 10', async () => { + it('getDelegate should return a delegate with missedRewardCalls', async () => { // given const delegate = createTranscoder() + const missedRewardCalls = 0 + // stubs the delegateGraphql service + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + // stubs getMissedRewardCalls method + const getMissedRewardCallsStub = sinon + .stub(delegateService, 'getMissedRewardCalls') + .returns(missedRewardCalls) + const resultExpected = { + ...delegate, + totalStake: tokenAmountInUnits(delegate.totalStake), + last30MissedRewardCalls: missedRewardCalls + } + // when - const result = await getDelegate() - console.log('Get delegate ', result) + const result = await delegateService.getDelegate() + // then + expect(getSummaryStub.called) + expect(getMissedRewardCallsStub.called) + expect(result.summary).to.deep.equal(resultExpected) }) }) describe('# getDelegateProtocolNextReward', () => { From ca4e6a80836253c54b13d54a744680334cfe7cbe Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Fri, 21 Jun 2019 14:31:33 -0300 Subject: [PATCH 03/20] adds getDelegateProtocolNextReward tests adds unitAmountInTokenUnits utils file --- config/constants.js | 4 +- server/helpers/delegateService.js | 1 + server/helpers/utils.js | 7 ++ test/server/helpers/delegate.test.js | 99 +++++++++++++++++++++++++++- 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/config/constants.js b/config/constants.js index 8580c4f..bfb3831 100644 --- a/config/constants.js +++ b/config/constants.js @@ -1,5 +1,7 @@ const PROTOCOL_DIVISION_BASE = 1000000 +const TOKEN_DECIMALS_MULTIPLIER = 1000000000000000000 module.exports = { - PROTOCOL_DIVISION_BASE + PROTOCOL_DIVISION_BASE, + TOKEN_DECIMALS_MULTIPLIER } diff --git a/server/helpers/delegateService.js b/server/helpers/delegateService.js index a8cd56c..f002d04 100644 --- a/server/helpers/delegateService.js +++ b/server/helpers/delegateService.js @@ -1,4 +1,5 @@ const _ = require('lodash') +const { MathBN } = require('../../server/helpers/utils') const { tokenAmountInUnits } = require('./utils') const { PROTOCOL_DIVISION_BASE } = require('../../config/constants') diff --git a/server/helpers/utils.js b/server/helpers/utils.js index 67dca6a..cd18fc6 100644 --- a/server/helpers/utils.js +++ b/server/helpers/utils.js @@ -1,3 +1,5 @@ +const { TOKEN_DECIMALS_MULTIPLIER } = require('../../config/constants') + const Big = require('big.js') const BN = require('bn.js') const { unitMap, toWei } = require('ethjs-unit') @@ -291,6 +293,10 @@ const tokenAmountInUnits = (amount, decimals = 18) => { return MathBN.div(amount, decimalsPerToken) } +const unitAmountInTokenUnits = amount => { + return MathBN.mul(amount, TOKEN_DECIMALS_MULTIPLIER) +} + const calculateMissedRewardCalls = (rewards, currentRound) => { if (!currentRound || !rewards) { return 0 @@ -354,6 +360,7 @@ module.exports = { getSubscriptorRole, getDelegatorRoundsUntilUnbonded, tokenAmountInUnits, + unitAmountInTokenUnits, calculateMissedRewardCalls, calculateNextRoundInflationRatio } diff --git a/test/server/helpers/delegate.test.js b/test/server/helpers/delegate.test.js index 7d2d33c..da802c3 100644 --- a/test/server/helpers/delegate.test.js +++ b/test/server/helpers/delegate.test.js @@ -1,4 +1,6 @@ -const { tokenAmountInUnits } = require('../../../server/helpers/utils') +const { MathBN } = require('../../../server/helpers/utils') + +const { tokenAmountInUnits, unitAmountInTokenUnits } = require('../../../server/helpers/utils') const { getDelegateService } = require('../../../server/helpers/delegateService') @@ -38,7 +40,100 @@ describe('## DelegateService test', () => { }) }) describe('# getDelegateProtocolNextReward', () => { - it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => {}) + // bondedStake = 400 + // totalSupply = 1000 + // delegateBondedStake = 40 (10%) + // inflation = 0.14% + // nextTokenRewards = 140 + // result (delegateReward) = 14 + it('140 minted tokens for next round, protocol bondedStake is 400, the bondedStake of the delegate is 40 (10% of the totalBonded), result should be 14 (10% of 140)', async () => { + // given + const delegate = createTranscoder() + delegate.totalStake = unitAmountInTokenUnits(40) + const totalBondedStake = unitAmountInTokenUnits(400) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const getMintedTokensForNextRoundStub = sinon + .stub(protocolSdk, 'getMintedTokensForNextRound') + .returns(140) + const getTotalBondedStub = sinon.stub(protocolSdk, 'getTotalBonded').returns(totalBondedStake) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const rewardExpected = '14' + + // when + const result = await delegateService.getDelegateProtocolNextReward() + + // then + expect(getSummaryStub.called) + expect(getMintedTokensForNextRoundStub.called) + expect(getTotalBondedStub.called) + expect(result).equal(rewardExpected) + }) + it('100 minted tokens for next round, protocol bondedStake is 1400, the bondedStake of the delegate is 512.4 (36.6% of the totalBonded), result should be 36.6', async () => { + // given + const delegate = createTranscoder() + delegate.totalStake = unitAmountInTokenUnits('512.4') + const totalBondedStake = unitAmountInTokenUnits(1400) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const getMintedTokensForNextRoundStub = sinon + .stub(protocolSdk, 'getMintedTokensForNextRound') + .returns(100) + const getTotalBondedStub = sinon.stub(protocolSdk, 'getTotalBonded').returns(totalBondedStake) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const rewardExpected = '36.6' + + // when + const result = await delegateService.getDelegateProtocolNextReward() + + // then + expect(getSummaryStub.called) + expect(getMintedTokensForNextRoundStub.called) + expect(getTotalBondedStub.called) + expect(result).equal(rewardExpected) + }) + it('0 minted tokens for next round, protocol bondedStake is 1400, the bondedStake of the delegate is 512.4 (36.6% of the totalBonded), result should be 0', async () => { + // given + const delegate = createTranscoder() + delegate.totalStake = unitAmountInTokenUnits('512.4') + const totalBondedStake = unitAmountInTokenUnits(1400) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const getMintedTokensForNextRoundStub = sinon + .stub(protocolSdk, 'getMintedTokensForNextRound') + .returns(0) + const getTotalBondedStub = sinon.stub(protocolSdk, 'getTotalBonded').returns(totalBondedStake) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const rewardExpected = '0' + + // when + const result = await delegateService.getDelegateProtocolNextReward() + + // then + expect(getSummaryStub.called) + expect(getMintedTokensForNextRoundStub.called) + expect(getTotalBondedStub.called) + expect(result).equal(rewardExpected) + }) + it('1000 minted tokens for next round, protocol bondedStake is 10000, the bondedStake of the delegate is 100 (1% of the totalBonded), result should be 10', async () => { + // given + const delegate = createTranscoder() + delegate.totalStake = unitAmountInTokenUnits('100') + const totalBondedStake = unitAmountInTokenUnits(10000) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const getMintedTokensForNextRoundStub = sinon + .stub(protocolSdk, 'getMintedTokensForNextRound') + .returns(1000) + const getTotalBondedStub = sinon.stub(protocolSdk, 'getTotalBonded').returns(totalBondedStake) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const rewardExpected = '10' + + // when + const result = await delegateService.getDelegateProtocolNextReward() + + // then + expect(getSummaryStub.called) + expect(getMintedTokensForNextRoundStub.called) + expect(getTotalBondedStub.called) + expect(result).equal(rewardExpected) + }) }) describe('# getDelegateNextReward', () => { it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => {}) From d50537f2f512493992904f749b44f5c963698f46 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Fri, 21 Jun 2019 15:54:49 -0300 Subject: [PATCH 04/20] Adds index file for graphql queries Adds createDelegator utils file Adds tests for getDelegateProtocolNextReward, getDelegateNextReward, getDelegateRewardToDelegators, getDelegatorNextReturn, getMissedRewardCalls --- server/helpers/delegateService.js | 23 +- server/helpers/graphql/queries/index.js | 15 + server/helpers/test/util.js | 25 +- test/server/helpers/delegate.test.js | 391 +++++++++++++++++++++++- 4 files changed, 431 insertions(+), 23 deletions(-) create mode 100644 server/helpers/graphql/queries/index.js diff --git a/server/helpers/delegateService.js b/server/helpers/delegateService.js index f002d04..a935263 100644 --- a/server/helpers/delegateService.js +++ b/server/helpers/delegateService.js @@ -6,10 +6,8 @@ const { PROTOCOL_DIVISION_BASE } = require('../../config/constants') const { calculateMissedRewardCalls } = require('./utils') -const { getCurrentRound } = require('./graphql/queries/protocol') - let delegateServiceInstance -const defaultDelegateSource = require('./graphql/queries/delegate') +const defaultDelegateSource = require('./graphql/queries/index') const defaultProtocolSource = require('./livepeerAPI') const getDelegateService = ( @@ -61,11 +59,11 @@ class DelegateService { // Receives a delegateAddress and returns the REAL reward of the delegate (nextReward*rewardCut) async getDelegateNextReward(delegateAddress) { - const { getDelegateSummary, getDelegateProtocolNextReward } = this.delegateSource + const { getDelegateSummary } = this.delegateSource // DelegateReward = DelegateProtocolNextReward * rewardCut let [summary, protocolNextReward] = await Promise.all([ getDelegateSummary(delegateAddress), - getDelegateProtocolNextReward(delegateAddress) + this.getDelegateProtocolNextReward(delegateAddress) ]) const { pendingRewardCut } = summary const rewardCut = MathBN.div(pendingRewardCut, PROTOCOL_DIVISION_BASE) @@ -74,11 +72,11 @@ class DelegateService { // For a given delegateAddress return the next reward that will be distributed towards delegators async getDelegateRewardToDelegators(delegateAddress) { - const { getDelegateSummary, getDelegateProtocolNextReward } = this.delegateSource + const { getDelegateSummary } = this.delegateSource // FORMULA: DelegateRewardToDelegators = DelegateProtocolNextReward - DelegateProtocolNextReward * rewardCut let [summary, protocolNextReward] = await Promise.all([ getDelegateSummary(delegateAddress), - getDelegateProtocolNextReward(delegateAddress) + this.getDelegateProtocolNextReward(delegateAddress) ]) const { pendingRewardCut } = summary const rewardCut = MathBN.div(pendingRewardCut, PROTOCOL_DIVISION_BASE) @@ -89,23 +87,22 @@ class DelegateService { // For a given delegatorAddress, returns the next round reward if exists async getDelegatorNextReturn(delegatorAddress) { const { getLivepeerDelegatorAccount } = this.protocolSource - const { getDelegateTotalStake, getDelegateRewardToDelegators } = this.delegateSource + const { getDelegateTotalStake } = this.delegateSource // FORMULA: rewardToDelegators * delegatorParticipationInTotalStake const delegator = await getLivepeerDelegatorAccount(delegatorAddress) const { delegateAddress, totalStake } = delegator const delegateTotalStake = await getDelegateTotalStake(delegateAddress) - // FORMULA: delegateTotalStake / totalStake - const delegatorParticipationInTotalStake = MathBN.div(delegateTotalStake, totalStake) - const rewardToDelegators = await getDelegateRewardToDelegators(delegateAddress) + // Delegator participation FORMULA: delegatorTotalStake / delegateTotalStake + const delegatorParticipationInTotalStake = MathBN.div(totalStake, delegateTotalStake) + const rewardToDelegators = await this.getDelegateRewardToDelegators(delegateAddress) return MathBN.mul(rewardToDelegators, delegatorParticipationInTotalStake) } async getMissedRewardCalls(delegateAddress) { - const { getDelegateRewards } = this.delegateSource + const { getDelegateRewards, getCurrentRound } = this.delegateSource let missedCalls = 0 const rewards = await getDelegateRewards(delegateAddress) const currentRound = await getCurrentRound() - if (rewards) { missedCalls = calculateMissedRewardCalls(rewards, currentRound) } diff --git a/server/helpers/graphql/queries/index.js b/server/helpers/graphql/queries/index.js new file mode 100644 index 0000000..47c2792 --- /dev/null +++ b/server/helpers/graphql/queries/index.js @@ -0,0 +1,15 @@ +const { + getDelegateSummary, + getDelegateRewards, + getDelegateTotalStake, + getRegisteredDelegates +} = require('./delegate') +const { getCurrentRound } = require('./protocol') + +module.exports = { + getDelegateSummary, + getDelegateRewards, + getDelegateTotalStake, + getRegisteredDelegates, + getCurrentRound +} diff --git a/server/helpers/test/util.js b/server/helpers/test/util.js index 985be36..876c916 100644 --- a/server/helpers/test/util.js +++ b/server/helpers/test/util.js @@ -40,8 +40,31 @@ const createTranscoder = transcoderId => { return mockTranscoder } +const createDelegator = delegatorId => { + const mockDelegator = { + address: delegatorId, + allowance: '9000000000000000000000', + bondedAmount: '1648721740335621049244', + delegateAddress: delegatorId, + delegatedAmount: '0', + fees: '0', + lastClaimRound: '1348', + pendingFees: '0', + pendingStake: '1880033099473791560404', + startRound: '1241', + status: 'Bonded', + withdrawRound: '0', + withdrawAmount: '0', + nextUnbondingLockId: '1', + totalStake: '1880033099473791560404' + } + + return mockDelegator +} + module.exports = { createRewardObject, createRoundObject, - createTranscoder + createTranscoder, + createDelegator } diff --git a/test/server/helpers/delegate.test.js b/test/server/helpers/delegate.test.js index da802c3..69a5d09 100644 --- a/test/server/helpers/delegate.test.js +++ b/test/server/helpers/delegate.test.js @@ -4,8 +4,12 @@ const { tokenAmountInUnits, unitAmountInTokenUnits } = require('../../../server/ const { getDelegateService } = require('../../../server/helpers/delegateService') -const { createTranscoder } = require('../../../server/helpers/test/util') -const delegatesGraphql = require('../../../server/helpers/graphql/queries/delegate') +const { + createTranscoder, + createDelegator, + createRewardObject +} = require('../../../server/helpers/test/util') +const delegatesGraphql = require('../../../server/helpers/graphql/queries/index') const protocolSdk = require('../../../server/helpers/livepeerAPI') const chai = require('chai') const expect = chai.expect @@ -37,6 +41,9 @@ describe('## DelegateService test', () => { expect(getSummaryStub.called) expect(getMissedRewardCallsStub.called) expect(result.summary).to.deep.equal(resultExpected) + // restore stubs + getSummaryStub.restore() + getMissedRewardCallsStub.restore() }) }) describe('# getDelegateProtocolNextReward', () => { @@ -67,6 +74,10 @@ describe('## DelegateService test', () => { expect(getMintedTokensForNextRoundStub.called) expect(getTotalBondedStub.called) expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getMintedTokensForNextRoundStub.restore() + getTotalBondedStub.restore() }) it('100 minted tokens for next round, protocol bondedStake is 1400, the bondedStake of the delegate is 512.4 (36.6% of the totalBonded), result should be 36.6', async () => { // given @@ -89,6 +100,10 @@ describe('## DelegateService test', () => { expect(getMintedTokensForNextRoundStub.called) expect(getTotalBondedStub.called) expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getMintedTokensForNextRoundStub.restore() + getTotalBondedStub.restore() }) it('0 minted tokens for next round, protocol bondedStake is 1400, the bondedStake of the delegate is 512.4 (36.6% of the totalBonded), result should be 0', async () => { // given @@ -111,6 +126,10 @@ describe('## DelegateService test', () => { expect(getMintedTokensForNextRoundStub.called) expect(getTotalBondedStub.called) expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getMintedTokensForNextRoundStub.restore() + getTotalBondedStub.restore() }) it('1000 minted tokens for next round, protocol bondedStake is 10000, the bondedStake of the delegate is 100 (1% of the totalBonded), result should be 10', async () => { // given @@ -133,21 +152,375 @@ describe('## DelegateService test', () => { expect(getMintedTokensForNextRoundStub.called) expect(getTotalBondedStub.called) expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getMintedTokensForNextRoundStub.restore() + getTotalBondedStub.restore() }) }) describe('# getDelegateNextReward', () => { - it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => {}) - }) - describe('# getDelegateRewardToDelegators', () => { - it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => {}) + it('delegatorRewardForNextRound = 1000, rewardCut = 10%, result should be 10', async () => { + // given + const delegate = createTranscoder() + delegate.pendingRewardCut = MathBN.mul(10, 10000) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateProtocolNextRewardStub = sinon + .stub(delegateService, 'getDelegateProtocolNextReward') + .returns(1000) + const rewardExpected = '100' + + // when + const result = await delegateService.getDelegateNextReward() + + // then + expect(getSummaryStub.called) + expect(getDelegateProtocolNextRewardStub.called) + expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getDelegateProtocolNextRewardStub.restore() + }) + it('delegatorRewardForNextRound = 198761, rewardCut = 10%, result should be 19876.1', async () => { + // given + const delegate = createTranscoder() + delegate.pendingRewardCut = MathBN.mul(10, 10000) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateProtocolNextRewardStub = sinon + .stub(delegateService, 'getDelegateProtocolNextReward') + .returns(198761) + const rewardExpected = '19876.1' + + // when + const result = await delegateService.getDelegateNextReward() + + // then + expect(getSummaryStub.called) + expect(getDelegateProtocolNextRewardStub.called) + expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getDelegateProtocolNextRewardStub.restore() + }) + it('delegatorRewardForNextRound = 0, rewardCut = 10%, result should be 0', async () => { + // given + const delegate = createTranscoder() + delegate.pendingRewardCut = MathBN.mul(10, 10000) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateProtocolNextRewardStub = sinon + .stub(delegateService, 'getDelegateProtocolNextReward') + .returns(0) + const rewardExpected = '0' + + // when + const result = await delegateService.getDelegateNextReward() + + // then + expect(getSummaryStub.called) + expect(getDelegateProtocolNextRewardStub.called) + expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getDelegateProtocolNextRewardStub.restore() + }) }) describe('# getDelegateRewardToDelegators', () => { - it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => {}) + it('delegateNextProtocolReward = 1000, rewardCut = 10%, result should be 900', async () => { + // given + const delegate = createTranscoder() + delegate.pendingRewardCut = MathBN.mul(10, 10000) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateProtocolNextRewardStub = sinon + .stub(delegateService, 'getDelegateProtocolNextReward') + .returns(1000) + const rewardExpected = '900' + + // when + const result = await delegateService.getDelegateRewardToDelegators() + + // then + expect(getSummaryStub.called) + expect(getDelegateProtocolNextRewardStub.called) + expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getDelegateProtocolNextRewardStub.restore() + }) + it('delegateNextProtocolReward = 19843.21064318, rewardCut = 10%, result should be 17859.889578862', async () => { + // given + const delegate = createTranscoder() + delegate.pendingRewardCut = MathBN.mul(10, 10000) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateProtocolNextRewardStub = sinon + .stub(delegateService, 'getDelegateProtocolNextReward') + .returns(19843.21064318) + const rewardExpected = '17858.889578862' + + // when + const result = await delegateService.getDelegateRewardToDelegators() + + // then + expect(getSummaryStub.called) + expect(getDelegateProtocolNextRewardStub.called) + expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getDelegateProtocolNextRewardStub.restore() + }) + it('delegateNextProtocolReward = 0, rewardCut = 10%, result should be 0', async () => { + // given + const delegate = createTranscoder() + delegate.pendingRewardCut = MathBN.mul(10, 10000) + const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateProtocolNextRewardStub = sinon + .stub(delegateService, 'getDelegateProtocolNextReward') + .returns(0) + const rewardExpected = '0' + + // when + const result = await delegateService.getDelegateRewardToDelegators() + + // then + expect(getSummaryStub.called) + expect(getDelegateProtocolNextRewardStub.called) + expect(result).equal(rewardExpected) + // restore stubs + getSummaryStub.restore() + getDelegateProtocolNextRewardStub.restore() + }) }) describe('# getDelegatorNextReturn', () => { - it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => {}) + // Delegate bondedStake = 1000 + // DelegatorBonded stake = 100 (10% participation) + // Delegate nextRewardToDelegators = 500 + // Result = 50 + it('the next reward to delegators is 500, the % of participation of the delegator is 10%, result should be 50', async () => { + // given + const delegator = createDelegator() + delegator.totalStake = unitAmountInTokenUnits(100) + const delegateTotalStake = unitAmountInTokenUnits(1000) + const getLivepeerDelegatorAccountSub = sinon + .stub(protocolSdk, 'getLivepeerDelegatorAccount') + .returns(delegator) + const getDelegateTotalStakeStub = sinon + .stub(delegatesGraphql, 'getDelegateTotalStake') + .returns(delegateTotalStake) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateRewardToDelegatorsSub = sinon + .stub(delegateService, 'getDelegateRewardToDelegators') + .returns(500) + const rewardExpected = '50' + + // when + const result = await delegateService.getDelegatorNextReturn() + + // then + expect(getLivepeerDelegatorAccountSub.called) + expect(getDelegateTotalStakeStub.called) + expect(getDelegateRewardToDelegatorsSub.called) + expect(result).equal(rewardExpected) + // restore stubs + getLivepeerDelegatorAccountSub.restore() + getDelegateTotalStakeStub.restore() + getDelegateRewardToDelegatorsSub.restore() + }) + it('the next reward to delegators is 4866341500, the % of participation of the delegator is 10%, result should be 486634150', async () => { + // given + const delegator = createDelegator() + delegator.totalStake = unitAmountInTokenUnits(100) + const delegateTotalStake = unitAmountInTokenUnits(1000) + const getLivepeerDelegatorAccountSub = sinon + .stub(protocolSdk, 'getLivepeerDelegatorAccount') + .returns(delegator) + const getDelegateTotalStakeStub = sinon + .stub(delegatesGraphql, 'getDelegateTotalStake') + .returns(delegateTotalStake) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateRewardToDelegatorsSub = sinon + .stub(delegateService, 'getDelegateRewardToDelegators') + .returns(4866341500) + const rewardExpected = '486634150' + + // when + const result = await delegateService.getDelegatorNextReturn() + + // then + expect(getLivepeerDelegatorAccountSub.called) + expect(getDelegateTotalStakeStub.called) + expect(getDelegateRewardToDelegatorsSub.called) + expect(result).equal(rewardExpected) + // restore stubs + getLivepeerDelegatorAccountSub.restore() + getDelegateTotalStakeStub.restore() + getDelegateRewardToDelegatorsSub.restore() + }) + it('the next reward to delegators is 4866341500, the % of participation of the delegator is 99%, result should be 4817678085', async () => { + // given + const delegator = createDelegator() + delegator.totalStake = unitAmountInTokenUnits(990) + const delegateTotalStake = unitAmountInTokenUnits(1000) + const getLivepeerDelegatorAccountSub = sinon + .stub(protocolSdk, 'getLivepeerDelegatorAccount') + .returns(delegator) + const getDelegateTotalStakeStub = sinon + .stub(delegatesGraphql, 'getDelegateTotalStake') + .returns(delegateTotalStake) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateRewardToDelegatorsSub = sinon + .stub(delegateService, 'getDelegateRewardToDelegators') + .returns(4866341500) + const rewardExpected = '4817678085' + + // when + const result = await delegateService.getDelegatorNextReturn() + + // then + expect(getLivepeerDelegatorAccountSub.called) + expect(getDelegateTotalStakeStub.called) + expect(getDelegateRewardToDelegatorsSub.called) + expect(result).equal(rewardExpected) + // restore stubs + getLivepeerDelegatorAccountSub.restore() + getDelegateTotalStakeStub.restore() + getDelegateRewardToDelegatorsSub.restore() + }) + it('the next reward to delegators is 0, the % of participation of the delegator is 99%, result should be 0', async () => { + // given + const delegator = createDelegator() + delegator.totalStake = unitAmountInTokenUnits(990) + const delegateTotalStake = unitAmountInTokenUnits(1000) + const getLivepeerDelegatorAccountSub = sinon + .stub(protocolSdk, 'getLivepeerDelegatorAccount') + .returns(delegator) + const getDelegateTotalStakeStub = sinon + .stub(delegatesGraphql, 'getDelegateTotalStake') + .returns(delegateTotalStake) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const getDelegateRewardToDelegatorsSub = sinon + .stub(delegateService, 'getDelegateRewardToDelegators') + .returns(0) + const rewardExpected = '0' + + // when + const result = await delegateService.getDelegatorNextReturn() + + // then + expect(getLivepeerDelegatorAccountSub.called) + expect(getDelegateTotalStakeStub.called) + expect(getDelegateRewardToDelegatorsSub.called) + expect(result).equal(rewardExpected) + // restore stubs + getLivepeerDelegatorAccountSub.restore() + getDelegateTotalStakeStub.restore() + getDelegateRewardToDelegatorsSub.restore() + }) }) describe('# getMissedRewardCalls', () => { - it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => {}) + describe('# Missed reward call calculation', () => { + it('There are 30 rounds, 10 of them do not have reward object, result should be 10', async () => { + // given + const rewards = [] + const transcoderId = '1' + const currentRound = { + id: '30' + } + for (let roundI = 1; roundI <= 30; roundI++) { + const newReward = createRewardObject(transcoderId, roundI) + if (roundI <= 10) { + newReward.rewardTokens = null + } + rewards.push(newReward) + } + const getDelegateRewardsStub = sinon + .stub(delegatesGraphql, 'getDelegateRewards') + .returns(rewards) + const getCurrentRoundStub = sinon + .stub(delegatesGraphql, 'getCurrentRound') + .returns(currentRound) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + + // when + const missedRewardCalls = await delegateService.getMissedRewardCalls(rewards, currentRound) + // then + expect(getDelegateRewardsStub.called) + expect(getCurrentRoundStub.called) + expect(missedRewardCalls).to.equal(10) + // restore stubs + getDelegateRewardsStub.restore() + getCurrentRoundStub.restore() + }) + it('There are 40 rounds, the firsts 5 of them do not have reward object, neither the last 10 of them, result should be 5', async () => { + // given + const rewards = [] + const transcoderId = '1' + const currentRound = { + id: 40 + } + for (let roundI = 1; roundI <= 40; roundI++) { + const newReward = createRewardObject(transcoderId, roundI) + if (roundI <= 5) { + newReward.rewardTokens = null + } + if (roundI >= 35) { + newReward.rewardTokens = null + } + rewards.push(newReward) + } + const getDelegateRewardsStub = sinon + .stub(delegatesGraphql, 'getDelegateRewards') + .returns(rewards) + const getCurrentRoundStub = sinon + .stub(delegatesGraphql, 'getCurrentRound') + .returns(currentRound) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + + // when + const missedRewardCalls = await delegateService.getMissedRewardCalls(rewards, currentRound) + + // then + expect(getDelegateRewardsStub.called) + expect(getCurrentRoundStub.called) + expect(missedRewardCalls).to.equal(5) + // restore stubs + getDelegateRewardsStub.restore() + getCurrentRoundStub.restore() + }) + it('There are 30 rounds, all of them have reward, result should be 0', async () => { + // given + const rewards = [] + const transcoderId = '1' + const currentRound = { + id: 30 + } + for (let roundI = 1; roundI <= 30; roundI++) { + const newReward = createRewardObject(transcoderId, roundI) + rewards.push(newReward) + } + + const getDelegateRewardsStub = sinon + .stub(delegatesGraphql, 'getDelegateRewards') + .returns(rewards) + const getCurrentRoundStub = sinon + .stub(delegatesGraphql, 'getCurrentRound') + .returns(currentRound) + const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + + // when + const missedRewardCalls = await delegateService.getMissedRewardCalls(rewards, currentRound) + + // then + expect(getDelegateRewardsStub.called) + expect(getCurrentRoundStub.called) + expect(missedRewardCalls).to.equal(0) + // restore stubs + getDelegateRewardsStub.restore() + getCurrentRoundStub.restore() + }) + }) }) }) From 5e822443872a6e357ef448390d808b90fe5639bd Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Fri, 21 Jun 2019 16:20:13 -0300 Subject: [PATCH 05/20] Removes util.test file, now the missed reward call calculation it's tested on the delegate test file --- test/util.test.js | 74 ----------------------------------------------- 1 file changed, 74 deletions(-) delete mode 100644 test/util.test.js diff --git a/test/util.test.js b/test/util.test.js deleted file mode 100644 index f1ffde9..0000000 --- a/test/util.test.js +++ /dev/null @@ -1,74 +0,0 @@ -const { createRewardObject } = require('../server/helpers/test/util') -const BN = require('bn.js') -const { calculateMissedRewardCalls } = require('../server/helpers/utils') -const chai = require('chai') // eslint-disable-line import/newline-after-import -const expect = chai.expect -const assert = chai.assert -const { MathBN } = require('../server/helpers/utils') - -chai.config.includeStack = true - -describe('## Utils file test', () => { - describe('# Missed reward call calculation', () => { - it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => { - // given - const rewards = [] - const transcoderId = '1' - const currentRound = { - id: 30 - } - for (let roundI = 1; roundI <= 30; roundI++) { - const newReward = createRewardObject(transcoderId, roundI) - if (roundI <= 10) { - newReward.rewardTokens = null - } - rewards.push(newReward) - } - // when - const missedRewardCalls = calculateMissedRewardCalls(rewards, currentRound) - // then - expect(missedRewardCalls).to.equal(10) - done() - }) - it('There are 40 rounds, the firsts 5 of them do not have reward object, neither the last 10 of them, result should be 5', done => { - // given - const rewards = [] - const transcoderId = '1' - const currentRound = { - id: 40 - } - for (let roundI = 1; roundI <= 40; roundI++) { - const newReward = createRewardObject(transcoderId, roundI) - if (roundI <= 5) { - newReward.rewardTokens = null - } - if (roundI >= 35) { - newReward.rewardTokens = null - } - rewards.push(newReward) - } - // when - const missedRewardCalls = calculateMissedRewardCalls(rewards, currentRound) - // then - expect(missedRewardCalls).to.equal(5) - done() - }) - it('There are 30 rounds, all of them have reward, result should be 0', done => { - // given - const rewards = [] - const transcoderId = '1' - const currentRound = { - id: 30 - } - for (let roundI = 1; roundI <= 30; roundI++) { - const newReward = createRewardObject(transcoderId, roundI) - rewards.push(newReward) - } - // when - const missedRewardCalls = calculateMissedRewardCalls(rewards, currentRound) - // then - expect(missedRewardCalls).to.equal(0) - done() - }) - }) -}) From 5fced6372ba62f37a3c8bc30d59674b264be5210 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Fri, 21 Jun 2019 16:57:42 -0300 Subject: [PATCH 06/20] Adds promiseRetry to delegateService --- server/helpers/delegateService.js | 45 +++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/server/helpers/delegateService.js b/server/helpers/delegateService.js index a935263..6ee5889 100644 --- a/server/helpers/delegateService.js +++ b/server/helpers/delegateService.js @@ -5,6 +5,7 @@ const { tokenAmountInUnits } = require('./utils') const { PROTOCOL_DIVISION_BASE } = require('../../config/constants') const { calculateMissedRewardCalls } = require('./utils') +const promiseRetry = require('promise-retry') let delegateServiceInstance const defaultDelegateSource = require('./graphql/queries/index') @@ -45,11 +46,15 @@ class DelegateService { const { getDelegateSummary } = this.delegateSource const { getMintedTokensForNextRound, getTotalBonded } = this.protocolSource // FORMULA: mintedTokensForNextRound * delegateParticipationInTotalBonded - let [summary, mintedTokensForNextRound, totalBondedInProtocol] = await Promise.all([ - getDelegateSummary(delegateAddress), - getMintedTokensForNextRound(), - getTotalBonded() - ]) + + let [summary, mintedTokensForNextRound, totalBondedInProtocol] = await promiseRetry(retry => { + return Promise.all([ + getDelegateSummary(delegateAddress), + getMintedTokensForNextRound(), + getTotalBonded() + ]).catch(err => retry()) + }) + const { totalStake } = summary // FORMULA: delegateTotalStake / protocolTotalBonded const participationInTotalBondedRatio = MathBN.div(totalStake, totalBondedInProtocol) @@ -61,10 +66,13 @@ class DelegateService { async getDelegateNextReward(delegateAddress) { const { getDelegateSummary } = this.delegateSource // DelegateReward = DelegateProtocolNextReward * rewardCut - let [summary, protocolNextReward] = await Promise.all([ - getDelegateSummary(delegateAddress), - this.getDelegateProtocolNextReward(delegateAddress) - ]) + let [summary, protocolNextReward] = await promiseRetry(retry => { + return Promise.all([ + getDelegateSummary(delegateAddress), + this.getDelegateProtocolNextReward(delegateAddress) + ]).catch(err => retry()) + }) + const { pendingRewardCut } = summary const rewardCut = MathBN.div(pendingRewardCut, PROTOCOL_DIVISION_BASE) return MathBN.mul(protocolNextReward, rewardCut) @@ -74,10 +82,13 @@ class DelegateService { async getDelegateRewardToDelegators(delegateAddress) { const { getDelegateSummary } = this.delegateSource // FORMULA: DelegateRewardToDelegators = DelegateProtocolNextReward - DelegateProtocolNextReward * rewardCut - let [summary, protocolNextReward] = await Promise.all([ - getDelegateSummary(delegateAddress), - this.getDelegateProtocolNextReward(delegateAddress) - ]) + let [summary, protocolNextReward] = await promiseRetry(retry => { + return Promise.all([ + getDelegateSummary(delegateAddress), + this.getDelegateProtocolNextReward(delegateAddress) + ]).catch(err => retry()) + }) + const { pendingRewardCut } = summary const rewardCut = MathBN.div(pendingRewardCut, PROTOCOL_DIVISION_BASE) const rewardToDelegate = MathBN.mul(protocolNextReward, rewardCut) @@ -89,7 +100,13 @@ class DelegateService { const { getLivepeerDelegatorAccount } = this.protocolSource const { getDelegateTotalStake } = this.delegateSource // FORMULA: rewardToDelegators * delegatorParticipationInTotalStake - const delegator = await getLivepeerDelegatorAccount(delegatorAddress) + const delegator = await promiseRetry(retry => { + try { + return getLivepeerDelegatorAccount(delegatorAddress) + } catch (err) { + retry() + } + }) const { delegateAddress, totalStake } = delegator const delegateTotalStake = await getDelegateTotalStake(delegateAddress) // Delegator participation FORMULA: delegatorTotalStake / delegateTotalStake From 3e60b15f542fb5b24460f4551de7dbc539adb35d Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Mon, 24 Jun 2019 11:00:42 -0300 Subject: [PATCH 07/20] Adds tests to util tests --- server/helpers/utils.js | 3 +- test/util.test.js | 196 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 test/util.test.js diff --git a/server/helpers/utils.js b/server/helpers/utils.js index cd18fc6..dbb1b15 100644 --- a/server/helpers/utils.js +++ b/server/helpers/utils.js @@ -362,5 +362,6 @@ module.exports = { tokenAmountInUnits, unitAmountInTokenUnits, calculateMissedRewardCalls, - calculateNextRoundInflationRatio + calculateNextRoundInflationRatio, + calculateCurrentBondingRate } diff --git a/test/util.test.js b/test/util.test.js new file mode 100644 index 0000000..b1974ba --- /dev/null +++ b/test/util.test.js @@ -0,0 +1,196 @@ +const { createRewardObject } = require('../server/helpers/test/util') +const { + calculateMissedRewardCalls, + calculateCurrentBondingRate, + calculateNextRoundInflationRatio, + tokenAmountInUnits +} = require('../server/helpers/utils') +const chai = require('chai') // eslint-disable-line import/newline-after-import +const expect = chai.expect +chai.config.includeStack = true + +describe('## Utils file test', () => { + describe('# Missed reward call calculation', () => { + it('There are 30 rounds, 10 of them do not have reward object, result should be 10', done => { + // given + const rewards = [] + const transcoderId = '1' + const currentRound = { + id: 30 + } + for (let roundI = 1; roundI <= 30; roundI++) { + const newReward = createRewardObject(transcoderId, roundI) + if (roundI <= 10) { + newReward.rewardTokens = null + } + rewards.push(newReward) + } + // when + const missedRewardCalls = calculateMissedRewardCalls(rewards, currentRound) + // then + expect(missedRewardCalls).to.equal(10) + done() + }) + it('There are 40 rounds, the firsts 5 of them do not have reward object, neither the last 10 of them, result should be 5', done => { + // given + const rewards = [] + const transcoderId = '1' + const currentRound = { + id: 40 + } + for (let roundI = 1; roundI <= 40; roundI++) { + const newReward = createRewardObject(transcoderId, roundI) + if (roundI <= 5) { + newReward.rewardTokens = null + } + if (roundI >= 35) { + newReward.rewardTokens = null + } + rewards.push(newReward) + } + // when + const missedRewardCalls = calculateMissedRewardCalls(rewards, currentRound) + // then + expect(missedRewardCalls).to.equal(5) + done() + }) + it('There are 30 rounds, all of them have reward, result should be 0', done => { + // given + const rewards = [] + const transcoderId = '1' + const currentRound = { + id: 30 + } + for (let roundI = 1; roundI <= 30; roundI++) { + const newReward = createRewardObject(transcoderId, roundI) + rewards.push(newReward) + } + // when + const missedRewardCalls = calculateMissedRewardCalls(rewards, currentRound) + // then + expect(missedRewardCalls).to.equal(0) + done() + }) + }) + describe('# Current bonding rate calculation', () => { + it('Total bonded is 100, total supply is 1000, the bonding rate should be 0.1 (10%)', done => { + // given + const totalBonded = 100 + const totalSupply = 1000 + const resultExpected = '0.1' + // when + const bondingRate = calculateCurrentBondingRate(totalBonded, totalSupply) + // then + expect(bondingRate).to.equal(resultExpected) + done() + }) + it('Total bonded is 0, total supply is 1000, the bonding rate should be 0 (0%)', done => { + // given + const totalBonded = 0 + const totalSupply = 1000 + const resultExpected = 0 + // when + const bondingRate = calculateCurrentBondingRate(totalBonded, totalSupply) + // then + expect(bondingRate).to.equal(resultExpected) + done() + }) + it('Total bonded is 1000, total supply is 1000, the bonding rate should be 1 (100%)', done => { + // given + const totalBonded = 1000 + const totalSupply = 1000 + const resultExpected = '1' + // when + const bondingRate = calculateCurrentBondingRate(totalBonded, totalSupply) + // then + expect(bondingRate).to.equal(resultExpected) + done() + }) + it('Total bonded is 999, total supply is 1000, the bonding rate should be 0.999 (99%)', done => { + // given + const totalBonded = 999 + const totalSupply = 1000 + const resultExpected = '0.999' + // when + const bondingRate = calculateCurrentBondingRate(totalBonded, totalSupply) + // then + expect(bondingRate).to.equal(resultExpected) + done() + }) + }) + describe('# Next inflation rate calculation', () => { + it('The inflation rate is 1000, the inflation change is 3, the currentBondingRate is bellow the targetCurrentRate, result should be 1003', done => { + // given + const inflationRate = 1000 + const inflationChange = 3 + const targetBondingRate = 50 + const totalBonded = 10 + const totalSupply = 1000 + const resultExpected = '1003' + // when + const nextRoundInflation = calculateNextRoundInflationRatio( + inflationRate, + inflationChange, + targetBondingRate, + totalBonded, + totalSupply + ) + // then + expect(nextRoundInflation).to.equal(resultExpected) + done() + }) + it('The inflation rate is 0, the inflation change is 3, the currentBondingRate is bellow the targetCurrentRate, result should be 0', done => { + // given + const inflationRate = 0 + const inflationChange = 3 + const targetBondingRate = 50 + const totalBonded = 10 + const totalSupply = 1000 + const resultExpected = '0' + // when + const nextRoundInflation = calculateNextRoundInflationRatio( + inflationRate, + inflationChange, + targetBondingRate, + totalBonded, + totalSupply + ) + // then + expect(nextRoundInflation).to.equal(resultExpected) + done() + }) + it('The inflation rate is 1000, the inflation change is 3, the currentBondingRate reached the targetCurrentRate, result should be 997', done => { + // given + const inflationRate = 1000 + const inflationChange = 3 + const targetBondingRate = 0.5 + const totalBonded = 999 + const totalSupply = 1000 + const resultExpected = '997' + // when + const nextRoundInflation = calculateNextRoundInflationRatio( + inflationRate, + inflationChange, + targetBondingRate, + totalBonded, + totalSupply + ) + // then + expect(nextRoundInflation).to.equal(resultExpected) + done() + }) + }) + describe('# Token amount in units', () => { + it('Should convert token units in units amount', done => { + // given + const amount = 1000000000000000111 + const decimals = 18 + const resultExpected = '1.0000000000000001' + // when + const amountInUnits = tokenAmountInUnits(amount) + // then + expect(amountInUnits).to.equal(resultExpected) + done() + }) + }) +}) From b61aa47866353864a48a3a402b4419ad9f76dbf3 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Mon, 24 Jun 2019 11:13:47 -0300 Subject: [PATCH 08/20] Update tsts --- test/util.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/util.test.js b/test/util.test.js index b1974ba..4d3f490 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -146,7 +146,7 @@ describe('## Utils file test', () => { const targetBondingRate = 50 const totalBonded = 10 const totalSupply = 1000 - const resultExpected = '0' + const resultExpected = 0 // when const nextRoundInflation = calculateNextRoundInflationRatio( inflationRate, From b260a55ab675787c8122e6b3e07f03585c5832b4 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Mon, 24 Jun 2019 12:33:11 -0300 Subject: [PATCH 09/20] Adds a TIMEOUT_THRESHOLD different than the default one (2000 ms) for the tests related to the SDK --- test/subscriber.test.js | 49 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/test/subscriber.test.js b/test/subscriber.test.js index 08c02f4..7474dd8 100644 --- a/test/subscriber.test.js +++ b/test/subscriber.test.js @@ -16,6 +16,8 @@ const getRandomId = () => { ) } +const TIMEOUT_THRESHOLD = 60000 // 1 minute + /** * root level hooks */ @@ -29,14 +31,12 @@ after(done => { describe('## Subscriber APIs', () => { let activatedTest = 1 - describe('# POST /api/subscribers', () => { let subscriber = { email: `mariano.aguero+${getRandomId()}@altoros.com`, address: '0x18AD183A875e5A42a60Eb5D3a9D6657C3493d064', frequency: 'weekly' } - const emailToUpdate = `mariano.aguero+${getRandomId()}@altoros.com` it('should create a new subscriber', done => { @@ -53,7 +53,7 @@ describe('## Subscriber APIs', () => { done() }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should not create a new subscriber with wrong email', done => { request(app) @@ -69,7 +69,7 @@ describe('## Subscriber APIs', () => { done() }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should not create a new subscriber with wrong frequency', done => { request(app) @@ -87,7 +87,7 @@ describe('## Subscriber APIs', () => { done() }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should not create an empty subscriber', done => { request(app) @@ -101,7 +101,7 @@ describe('## Subscriber APIs', () => { done() }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) }) describe('# POST /api/subscribers/activate', () => { @@ -142,7 +142,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should create a new subscriber to activate and give an error', done => { request(app) @@ -169,7 +169,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) }) describe('# GET /api/subscribers/:subscriberId', () => { @@ -200,7 +200,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should report error with message - Not found, when subscriber does not exists', done => { request(app) @@ -211,7 +211,7 @@ describe('## Subscriber APIs', () => { done() }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) }) describe('# PUT /api/subscribers/:subscriberId I', () => { @@ -250,7 +250,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should update subscriber with wrong email and get an error', done => { let subscriber = { @@ -284,7 +284,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should update subscriber with empty email and get an error', done => { let subscriber = { @@ -320,7 +320,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should update subscriber address details', done => { let subscriber = { @@ -353,7 +353,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) }) describe('# PUT /api/subscribers/:subscriberId II', () => { @@ -389,7 +389,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should update subscriber with empty address and get an error', done => { let subscriber = { @@ -423,7 +423,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should update subscriber frequency details', done => { let subscriber = { @@ -456,7 +456,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should update subscriber with wrong frequency and get an error', done => { let subscriber = { @@ -492,7 +492,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should update subscriber with empty frequency and get an error', done => { let subscriber = { @@ -528,7 +528,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) }) describe('# GET /api/subscribers/', () => { @@ -541,7 +541,7 @@ describe('## Subscriber APIs', () => { done() }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) it('should get all subscribers (with limit and skip)', done => { request(app) @@ -553,7 +553,7 @@ describe('## Subscriber APIs', () => { done() }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) }) describe('# DELETE /api/subscribers/', () => { @@ -563,7 +563,6 @@ describe('## Subscriber APIs', () => { address: '0x18AD183A875e5A42a60Eb5D3a9D6657C3493d064', frequency: 'weekly' } - request(app) .post('/api/subscribers') .send(subscriber) @@ -584,7 +583,7 @@ describe('## Subscriber APIs', () => { .catch(done) }) .catch(done) - }) + }).timeout(TIMEOUT_THRESHOLD) }) describe('# GET /api/subscribers/summary/:addresss', function() { @@ -638,7 +637,7 @@ describe('## Subscriber APIs', () => { }) .catch(done) }) - }) + }).timeout(TIMEOUT_THRESHOLD) }) describe('# GET /api/subscribers/address/:addresss', function() { @@ -668,6 +667,6 @@ describe('## Subscriber APIs', () => { }) .catch(done) }) - }) + }).timeout(TIMEOUT_THRESHOLD) }) }) From 99952b649f5fae1805dbc94006da63b27e749119 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Mon, 24 Jun 2019 17:11:14 -0300 Subject: [PATCH 10/20] Implements protocolService with configurable cache - improves performance on querys Adds delegatorService and protocolService with configurable source -> use dependencies injection accept receiving a dataSource (graphql or sdk) for data fetching --- config/constants.js | 4 +- server/delegate/delegate.controller.js | 2 +- server/earning/earning.model.js | 13 +- server/helpers/livepeerAPI.js | 212 ------------------ server/helpers/sdk/delegate.js | 19 ++ server/helpers/sdk/delegator.js | 39 ++++ server/helpers/sdk/index.js | 39 ++++ server/helpers/sdk/protocol.js | 95 ++++++++ .../helpers/{ => services}/delegateService.js | 45 ++-- server/helpers/services/delegatorService.js | 35 +++ server/helpers/services/protocolService.js | 197 ++++++++++++++++ server/subscriber/subscriber.controller.js | 37 +-- test/server/helpers/delegate.test.js | 2 +- 13 files changed, 478 insertions(+), 261 deletions(-) delete mode 100644 server/helpers/livepeerAPI.js create mode 100644 server/helpers/sdk/delegate.js create mode 100644 server/helpers/sdk/delegator.js create mode 100644 server/helpers/sdk/index.js create mode 100644 server/helpers/sdk/protocol.js rename server/helpers/{ => services}/delegateService.js (77%) create mode 100644 server/helpers/services/delegatorService.js create mode 100644 server/helpers/services/protocolService.js diff --git a/config/constants.js b/config/constants.js index bfb3831..9d23921 100644 --- a/config/constants.js +++ b/config/constants.js @@ -1,7 +1,9 @@ const PROTOCOL_DIVISION_BASE = 1000000 const TOKEN_DECIMALS_MULTIPLIER = 1000000000000000000 +const CACHE_UPDATE_INTERVAL = 1000 * 60 * 60 * 2 // Updates every 2 hours module.exports = { PROTOCOL_DIVISION_BASE, - TOKEN_DECIMALS_MULTIPLIER + TOKEN_DECIMALS_MULTIPLIER, + CACHE_UPDATE_INTERVAL } diff --git a/server/delegate/delegate.controller.js b/server/delegate/delegate.controller.js index 8f60dfe..1054aa7 100644 --- a/server/delegate/delegate.controller.js +++ b/server/delegate/delegate.controller.js @@ -5,7 +5,7 @@ const { MathBN, tokenAmountInUnits } = require('../helpers/utils') const BN = require('bn.js') -const { getDelegateService } = require('../helpers/delegateService') +const { getDelegateService } = require('../helpers/services/delegateService') const getByAddress = async (req, res, next) => { const { address } = req.params diff --git a/server/earning/earning.model.js b/server/earning/earning.model.js index b2d0351..705d61c 100644 --- a/server/earning/earning.model.js +++ b/server/earning/earning.model.js @@ -1,9 +1,8 @@ +const { getProtocolService } = require('../helpers/services/protocolService') +const { getDelegatorService } = require('../helpers/services/delegatorService') + const Promise = require('bluebird') const mongoose = require('mongoose') -const { - getLivepeerDelegatorAccount, - getLivepeerCurrentRoundInfo -} = require('../helpers/livepeerAPI') const { MathBN } = require('../helpers/utils') /** * Earning Schema @@ -64,9 +63,11 @@ EarningSchema.statics = { */ async save(subscriber) { const { address, email } = subscriber + const delegatorService = getDelegatorService() + const protocolService = getProtocolService() let [delegator, currentRoundInfo] = await Promise.all([ - getLivepeerDelegatorAccount(address), - getLivepeerCurrentRoundInfo() + delegatorService.getDelegatorAccount(address), + protocolService.getLivepeerCurrentRoundInfo() ]) const { lastClaimRound, pendingStake, bondedAmount } = delegator diff --git a/server/helpers/livepeerAPI.js b/server/helpers/livepeerAPI.js deleted file mode 100644 index 0975376..0000000 --- a/server/helpers/livepeerAPI.js +++ /dev/null @@ -1,212 +0,0 @@ -const LivepeerSDK = require('@mariano-aguero/sdk') -const { MathBN, calculateNextRoundInflationRatio, tokenAmountInUnits } = require('./utils') -const { PROTOCOL_DIVISION_BASE } = require('../../config/constants') - -const getLivepeerTranscoders = async () => { - const { rpc } = await LivepeerSDK.default() - return await rpc.getTranscoders() -} - -const getLivepeerDelegatorAccount = async address => { - if (!address) { - return null - } - const { rpc } = await LivepeerSDK.default() - const summary = await rpc.getDelegator(address) - - summary.totalStake = getTotalStakeFromSummary(summary) - return summary -} - -const getLivepeerTranscoderAccount = async address => { - if (!address) { - return null - } - const { rpc } = await LivepeerSDK.default() - return await rpc.getTranscoder(address) -} - -const getLivepeerCurrentRound = async () => { - const { rpc } = await LivepeerSDK.default() - return await rpc.getCurrentRound() -} - -const getLivepeerLastInitializedRound = async () => { - const { rpc } = await LivepeerSDK.default() - return await rpc.getLastInitializedRound() -} - -const getLivepeerCurrentRoundInfo = async () => { - const { rpc } = await LivepeerSDK.default() - return await rpc.getCurrentRoundInfo() -} - -const getLivepeerRoundLength = async () => { - const { rpc } = await LivepeerSDK.default() - return await rpc.getRoundLength() -} - -const getLivepeerRoundsPerYear = async () => { - const { rpc } = await LivepeerSDK.default() - return await rpc.getRoundsPerYear() -} - -const getLivepeerDelegatorTokenBalance = async address => { - if (!address) { - return null - } - const { rpc } = await LivepeerSDK.default() - return await rpc.getTokenBalance(address) -} - -const getLivepeerDelegatorStake = async address => { - if (!address) { - return null - } - const { rpc } = await LivepeerSDK.default() - const summary = await rpc.getDelegator(address) - return getTotalStakeFromSummary(summary) -} - -const getTotalStakeFromSummary = summary => { - const { bondedAmount = 0, pendingStake = 0 } = summary - return MathBN.max(bondedAmount, pendingStake) -} - -const getTokenTotalSupply = async () => { - const { rpc } = await LivepeerSDK.default() - return rpc.getTokenTotalSupply() -} - -// Returns the inflation of the current round, the value should be divided by 1.000.000 in order to make it a ratio -const getInflationRate = async () => { - const { rpc } = await LivepeerSDK.default() - const inflation = await rpc.getInflation() - return MathBN.div(inflation, PROTOCOL_DIVISION_BASE) -} - -// Returns the change of inflation for the next round, the value should be divided by 1.000.000 in order to make it a ratio -const getInflationChange = async () => { - const { rpc } = await LivepeerSDK.default() - const inflationChange = await rpc.getInflationChange() - return MathBN.div(inflationChange, PROTOCOL_DIVISION_BASE) -} - -// Returns the inflation as a ratio for the next round, the value should be divided by 1.000.000 in order to make it a ratio -const getNextRoundInflation = async () => { - let [ - inflationRate, - inflationChange, - targetBondingRate, - totalBonded, - totalSupply - ] = await Promise.all([ - getInflationRate(), - getInflationChange(), - getTargetBondingRate(), - getTotalBonded(), - getTokenTotalSupply() - ]) - return calculateNextRoundInflationRatio( - inflationRate, - inflationChange, - targetBondingRate, - totalBonded, - totalSupply - ) -} - -// Returns the targetBondingRate, the value should be divided by 1.000.000 in order to make it a ratio -const getTargetBondingRate = async () => { - const { rpc } = await LivepeerSDK.default() - const target = await rpc.getTargetBondingRate() - return MathBN.div(target, PROTOCOL_DIVISION_BASE) -} - -// Returns the total amount of tokens bonded in the protocol -const getTotalBonded = async () => { - const { rpc } = await LivepeerSDK.default() - return await rpc.getTotalBonded() -} - -// Returns the amount of minted tokens for the next round (inflation * totalSupply) -const getMintedTokensForNextRound = async () => { - let [nextInflation, totalSupply] = await Promise.all([ - getNextRoundInflation(), - getTokenTotalSupply() - ]) - const mintedTokens = MathBN.mul(totalSupply, nextInflation) - return tokenAmountInUnits(mintedTokens) -} - -const getLivepeerDefaultConstants = async () => { - const { constants } = await LivepeerSDK.default() - const { Bonded, Pending, Unbonded, Unbonding } = constants.DELEGATOR_STATUS - return { - DELEGATOR_STATUS: { - Bonded, - Pending, - Unbonded, - Unbonding - }, - ROLE: { - DELEGATOR: 'Delegator', - TRANSCODER: 'Transcoder' - } - } -} - -const getLivepeerLatestBlock = async () => { - const { rpc } = await LivepeerSDK.default() - return await rpc.getBlock('latest') -} - -const getLivepeerRoundProgress = async () => { - const [currentRoundInfo, roundLength, latestBlock] = await Promise.all([ - getLivepeerCurrentRoundInfo(), - getLivepeerRoundLength(), - getLivepeerLatestBlock() - ]) - - const { id, initialized, lastInitializedRound, length, startBlock } = currentRoundInfo - const { number } = latestBlock - const nextRoundStartBlock = MathBN.add(startBlock, length) - - const nextRoundNum = MathBN.add(id, '1') - const blocksUntilNextRound = MathBN.sub(nextRoundStartBlock - number) - - return { - roundId: id, - isInitialized: initialized, - lastInitializedRound: lastInitializedRound, - length: length, - startBlock: startBlock, - blocksUntilNextRound: blocksUntilNextRound, - nextRoundStartBlock: nextRoundStartBlock, - roundLength: roundLength, - nextRoundNum: nextRoundNum, - progress: length > 0 ? (blocksUntilNextRound * 100) / length : 0 - } -} - -module.exports = { - getLivepeerTranscoders, - getLivepeerDelegatorAccount, - getLivepeerTranscoderAccount, - getLivepeerCurrentRound, - getLivepeerDelegatorTokenBalance, - getLivepeerDelegatorStake, - getLivepeerCurrentRoundInfo, - getLivepeerLastInitializedRound, - getLivepeerDefaultConstants, - getLivepeerRoundLength, - getLivepeerRoundsPerYear, - getLivepeerLatestBlock, - getLivepeerRoundProgress, - getInflationRate, - getInflationChange, - getNextRoundInflation, - getTotalBonded, - getTargetBondingRate, - getMintedTokensForNextRound -} diff --git a/server/helpers/sdk/delegate.js b/server/helpers/sdk/delegate.js new file mode 100644 index 0000000..93349f1 --- /dev/null +++ b/server/helpers/sdk/delegate.js @@ -0,0 +1,19 @@ +const LivepeerSDK = require('@mariano-aguero/sdk') + +const getLivepeerTranscoders = async () => { + const { rpc } = await LivepeerSDK.default() + return await rpc.getTranscoders() +} + +const getLivepeerTranscoderAccount = async address => { + if (!address) { + return null + } + const { rpc } = await LivepeerSDK.default() + return await rpc.getTranscoder(address) +} + +module.exports = { + getLivepeerTranscoders, + getLivepeerTranscoderAccount +} diff --git a/server/helpers/sdk/delegator.js b/server/helpers/sdk/delegator.js new file mode 100644 index 0000000..daf8683 --- /dev/null +++ b/server/helpers/sdk/delegator.js @@ -0,0 +1,39 @@ +const LivepeerSDK = require('@mariano-aguero/sdk') +const getLivepeerDelegatorAccount = async address => { + if (!address) { + return null + } + const { rpc } = await LivepeerSDK.default() + const summary = await rpc.getDelegator(address) + + summary.totalStake = getTotalStakeFromSummary(summary) + return summary +} + +const getLivepeerDelegatorTokenBalance = async address => { + if (!address) { + return null + } + const { rpc } = await LivepeerSDK.default() + return await rpc.getTokenBalance(address) +} + +const getLivepeerDelegatorStake = async address => { + if (!address) { + return null + } + const { rpc } = await LivepeerSDK.default() + const summary = await rpc.getDelegator(address) + return getTotalStakeFromSummary(summary) +} + +const getTotalStakeFromSummary = summary => { + const { bondedAmount = 0, pendingStake = 0 } = summary + return MathBN.max(bondedAmount, pendingStake) +} + +module.exports = { + getLivepeerDelegatorAccount, + getLivepeerDelegatorTokenBalance, + getLivepeerDelegatorStake +} diff --git a/server/helpers/sdk/index.js b/server/helpers/sdk/index.js new file mode 100644 index 0000000..8adf29f --- /dev/null +++ b/server/helpers/sdk/index.js @@ -0,0 +1,39 @@ +const { getLivepeerTranscoderAccount, getLivepeerTranscoders } = require('./delegate') +const { + getLivepeerCurrentRound, + getTotalBonded, + getInflationChange, + getInflationRate, + getLivepeerCurrentRoundInfo, + getLivepeerDefaultConstants, + getLivepeerLastInitializedRound, + getLivepeerLatestBlock, + getLivepeerRoundLength, + getLivepeerRoundsPerYear, + getTargetBondingRate +} = require('./protocol') + +const { + getLivepeerDelegatorTokenBalance, + getLivepeerDelegatorStake, + getLivepeerDelegatorAccount +} = require('./delegator') + +module.exports = { + getLivepeerDelegatorAccount, + getLivepeerDelegatorStake, + getLivepeerDelegatorTokenBalance, + getLivepeerTranscoderAccount, + getLivepeerTranscoders, + getLivepeerCurrentRound, + getTotalBonded, + getInflationChange, + getInflationRate, + getLivepeerCurrentRoundInfo, + getLivepeerDefaultConstants, + getLivepeerLastInitializedRound, + getLivepeerLatestBlock, + getLivepeerRoundLength, + getLivepeerRoundsPerYear, + getTargetBondingRate +} diff --git a/server/helpers/sdk/protocol.js b/server/helpers/sdk/protocol.js new file mode 100644 index 0000000..e91c06f --- /dev/null +++ b/server/helpers/sdk/protocol.js @@ -0,0 +1,95 @@ +const { PROTOCOL_DIVISION_BASE } = require('../../../config/constants') +const LivepeerSDK = require('@mariano-aguero/sdk') + +const getLivepeerCurrentRound = async () => { + const { rpc } = await LivepeerSDK.default() + return await rpc.getCurrentRound() +} + +const getLivepeerLastInitializedRound = async () => { + const { rpc } = await LivepeerSDK.default() + return await rpc.getLastInitializedRound() +} + +const getLivepeerCurrentRoundInfo = async () => { + const { rpc } = await LivepeerSDK.default() + return await rpc.getCurrentRoundInfo() +} + +const getLivepeerRoundLength = async () => { + const { rpc } = await LivepeerSDK.default() + return await rpc.getRoundLength() +} + +const getLivepeerRoundsPerYear = async () => { + const { rpc } = await LivepeerSDK.default() + return await rpc.getRoundsPerYear() +} +const getTokenTotalSupply = async () => { + const { rpc } = await LivepeerSDK.default() + return rpc.getTokenTotalSupply() +} + +// Returns the inflation of the current round, the value should be divided by 1.000.000 in order to make it a ratio +const getInflationRate = async () => { + const { rpc } = await LivepeerSDK.default() + const inflation = await rpc.getInflation() + return MathBN.div(inflation, PROTOCOL_DIVISION_BASE) +} + +// Returns the change of inflation for the next round, the value should be divided by 1.000.000 in order to make it a ratio +const getInflationChange = async () => { + const { rpc } = await LivepeerSDK.default() + const inflationChange = await rpc.getInflationChange() + return MathBN.div(inflationChange, PROTOCOL_DIVISION_BASE) +} + +// Returns the targetBondingRate, the value should be divided by 1.000.000 in order to make it a ratio +const getTargetBondingRate = async () => { + const { rpc } = await LivepeerSDK.default() + const target = await rpc.getTargetBondingRate() + return MathBN.div(target, PROTOCOL_DIVISION_BASE) +} + +// Returns the total amount of tokens bonded in the protocol +const getTotalBonded = async () => { + const { rpc } = await LivepeerSDK.default() + return await rpc.getTotalBonded() +} + +const getLivepeerDefaultConstants = async () => { + const { constants } = await LivepeerSDK.default() + const { Bonded, Pending, Unbonded, Unbonding } = constants.DELEGATOR_STATUS + return { + DELEGATOR_STATUS: { + Bonded, + Pending, + Unbonded, + Unbonding + }, + ROLE: { + DELEGATOR: 'Delegator', + TRANSCODER: 'Transcoder' + } + } +} + +const getLivepeerLatestBlock = async () => { + const { rpc } = await LivepeerSDK.default() + return await rpc.getBlock('latest') +} + +module.exports = { + getLivepeerCurrentRound, + getLivepeerLastInitializedRound, + getLivepeerCurrentRoundInfo, + getLivepeerRoundLength, + getLivepeerRoundsPerYear, + getTokenTotalSupply, + getInflationRate, + getInflationChange, + getTargetBondingRate, + getTotalBonded, + getLivepeerDefaultConstants, + getLivepeerLatestBlock +} diff --git a/server/helpers/delegateService.js b/server/helpers/services/delegateService.js similarity index 77% rename from server/helpers/delegateService.js rename to server/helpers/services/delegateService.js index 6ee5889..0d83ef5 100644 --- a/server/helpers/delegateService.js +++ b/server/helpers/services/delegateService.js @@ -1,35 +1,32 @@ +const { getProtocolService } = require('./protocolService') + const _ = require('lodash') -const { MathBN } = require('../../server/helpers/utils') -const { tokenAmountInUnits } = require('./utils') +const { MathBN } = require('../utils') +const { tokenAmountInUnits } = require('../utils') -const { PROTOCOL_DIVISION_BASE } = require('../../config/constants') +const { PROTOCOL_DIVISION_BASE } = require('../../../config/constants') -const { calculateMissedRewardCalls } = require('./utils') +const { calculateMissedRewardCalls } = require('../utils') const promiseRetry = require('promise-retry') let delegateServiceInstance -const defaultDelegateSource = require('./graphql/queries/index') -const defaultProtocolSource = require('./livepeerAPI') +const delegatesSource = require('../graphql/queries') // the default source for delegates is GRAPHQL -const getDelegateService = ( - delegateSource = defaultDelegateSource, - protocolSource = defaultProtocolSource -) => { +const getDelegateService = (source = delegatesSource) => { if (!delegateServiceInstance) { - delegateServiceInstance = new DelegateService(delegateSource, protocolSource) + delegateServiceInstance = new DelegateService(source) } return delegateServiceInstance } class DelegateService { - constructor(delegateDataSource, protocolDataSource) { - this.delegateSource = delegateDataSource - this.protocolSource = protocolDataSource + constructor(source) { + this.source = source } // Returns the delegate summary plus the missed reward calls async getDelegate(delegateAddress) { - const { getDelegateSummary } = this.delegateSource + const { getDelegateSummary } = this.source const summary = await getDelegateSummary(delegateAddress) const last30MissedRewardCalls = await this.getMissedRewardCalls(delegateAddress) return { @@ -43,8 +40,9 @@ class DelegateService { // Receives a delegateAddress and returns the TOTAL reward (protocol reward, no the reward cut) of that delegate for the next round async getDelegateProtocolNextReward(delegateAddress) { - const { getDelegateSummary } = this.delegateSource - const { getMintedTokensForNextRound, getTotalBonded } = this.protocolSource + const { getDelegateSummary } = this.source + const protocolService = getProtocolService() + const { getMintedTokensForNextRound, getTotalBonded } = protocolService // FORMULA: mintedTokensForNextRound * delegateParticipationInTotalBonded let [summary, mintedTokensForNextRound, totalBondedInProtocol] = await promiseRetry(retry => { @@ -64,7 +62,7 @@ class DelegateService { // Receives a delegateAddress and returns the REAL reward of the delegate (nextReward*rewardCut) async getDelegateNextReward(delegateAddress) { - const { getDelegateSummary } = this.delegateSource + const { getDelegateSummary } = this.source // DelegateReward = DelegateProtocolNextReward * rewardCut let [summary, protocolNextReward] = await promiseRetry(retry => { return Promise.all([ @@ -80,7 +78,7 @@ class DelegateService { // For a given delegateAddress return the next reward that will be distributed towards delegators async getDelegateRewardToDelegators(delegateAddress) { - const { getDelegateSummary } = this.delegateSource + const { getDelegateSummary } = this.source // FORMULA: DelegateRewardToDelegators = DelegateProtocolNextReward - DelegateProtocolNextReward * rewardCut let [summary, protocolNextReward] = await promiseRetry(retry => { return Promise.all([ @@ -97,8 +95,9 @@ class DelegateService { // For a given delegatorAddress, returns the next round reward if exists async getDelegatorNextReturn(delegatorAddress) { - const { getLivepeerDelegatorAccount } = this.protocolSource - const { getDelegateTotalStake } = this.delegateSource + const protocolService = getProtocolService() + const { getLivepeerDelegatorAccount } = protocolService + const { getDelegateTotalStake } = this.source // FORMULA: rewardToDelegators * delegatorParticipationInTotalStake const delegator = await promiseRetry(retry => { try { @@ -116,7 +115,9 @@ class DelegateService { } async getMissedRewardCalls(delegateAddress) { - const { getDelegateRewards, getCurrentRound } = this.delegateSource + const { getDelegateRewards } = this.source + const protocolService = getProtocolService() + const { getCurrentRound } = protocolService let missedCalls = 0 const rewards = await getDelegateRewards(delegateAddress) const currentRound = await getCurrentRound() diff --git a/server/helpers/services/delegatorService.js b/server/helpers/services/delegatorService.js new file mode 100644 index 0000000..c23f345 --- /dev/null +++ b/server/helpers/services/delegatorService.js @@ -0,0 +1,35 @@ +const _ = require('lodash') +let delegatorServiceInstance +const defaultSource = require('../sdk/delegator') // the delegate information comes from the SDK as default, graphql is not implemented + +const getDelegatorService = (source = defaultSource) => { + if (!delegatorServiceInstance) { + delegatorServiceInstance = new DelegatorService(source) + } + return delegatorServiceInstance +} + +class DelegatorService { + constructor(source) { + this.source = source + } + + async getDelegatorAccount(address) { + const { getLivepeerDelegatorAccount } = this.source + return await getLivepeerDelegatorAccount(address) + } + + async getDelegatorTokenBalance(address) { + const { getLivepeerDelegatorTokenBalance } = this.source + return await getLivepeerDelegatorTokenBalance(address) + } + + async getLivepeerDelegatorStake(address) { + const { getLivepeerDelegatorStake } = this.source + return await getLivepeerDelegatorStake(address) + } +} + +module.exports = { + getDelegatorService +} diff --git a/server/helpers/services/protocolService.js b/server/helpers/services/protocolService.js new file mode 100644 index 0000000..b09e299 --- /dev/null +++ b/server/helpers/services/protocolService.js @@ -0,0 +1,197 @@ +const { calculateNextRoundInflationRatio, tokenAmountInUnits } = require('../utils') + +const { CACHE_UPDATE_INTERVAL, PROTOCOL_DIVISION_BASE } = require('../../../config/constants') + +const defaultProtocolSource = require('../sdk/protocol') +let protocolServiceInstance + +const getProtocolService = (source = defaultProtocolSource) => { + if (!protocolServiceInstance) { + protocolServiceInstance = new ProtocolService(source) + } + return protocolServiceInstance +} + +class ProtocolService { + constructor(source) { + // The source of the functions that fetch data of the protocol, currently we are only supporting SDK + this.source = source + this.currentRound = null + this.defaultConstants = null + this.totalBonded = null + this.targetBondingRate = null + this.inflationChange = null + this.inflationRate = null + this.totalTokenSupply = null + this.lastInitializedRound = null + this.currentRoundLenght = null + this.currentRoundInfo = null + this.roundsPerYear = null + + // Sets an interval that will reset the cached values periodically + setInterval(() => { + this.currentRound = null + this.defaultConstants = null + this.totalBonded = null + this.targetBondingRate = null + this.inflationChange = null + this.inflationRate = null + this.totalTokenSupply = null + this.lastInitializedRound = null + this.currentRoundLenght = null + this.currentRoundInfo = null + this.roundsPerYear = null + }, CACHE_UPDATE_INTERVAL) + } + + async getTokenTotalSupply() { + if (!this.totalTokenSupply) { + this.totalTokenSupply = await this.source.getTokenTotalSupply() + } + return this.totalTokenSupply + } + + // Returns the inflation of the current round, the value should be divided by 1.000.000 in order to make it a ratio + async getInflationRate() { + if (!this.inflationRate) { + const inflation = await this.source.getInflation() + this.inflationRate = MathBN.div(inflation, PROTOCOL_DIVISION_BASE) + } + return this.inflationRate + } + + // Returns the change of inflation for the next round, the value should be divided by 1.000.000 in order to make it a ratio + async getInflationChange() { + if (!this.inflationChange) { + const inflationChange = await this.source.getInflationChange() + this.inflationChange = MathBN.div(inflationChange, PROTOCOL_DIVISION_BASE) + } + return this.inflationChange + } + + async getLastInitializedRound() { + if (!this.lastInitializedRound) { + this.lastInitializedRound = await this.source.getLastInitializedRound() + } + return this.lastInitializedRound + } + + async getCurrentRoundInfo() { + if (!this.currentRoundInfo) { + this.currentRoundInfo = await this.source.getLivepeerCurrentRoundInfo() + } + return this.currentRoundInfo + } + + async getRoundLength() { + if (!this.currentRoundLenght) { + this.currentRoundLenght = await this.source.getRoundLength() + } + } + + async getRoundsPerYear() { + if (!this.roundsPerYear) { + this.roundsPerYear = await this.source.getRoundsPerYear() + } + } + async getCurrentRound() { + if (!this.currentRound) { + this.currentRound = await this.source.getCurrentRound() + } + return this.currentRound + } + + // Returns the targetBondingRate, the value should be divided by 1.000.000 in order to make it a ratio + async getTargetBondingRate() { + if (!this.targetBondingRate) { + const target = await this.source.getTargetBondingRate() + this.targetBondingRate = MathBN.div(target, PROTOCOL_DIVISION_BASE) + } + return this.targetBondingRate + } + + // Returns the total amount of tokens bonded in the protocol + async getTotalBonded() { + if (!this.totalBonded) { + this.totalBonded = await this.source.getTotalBonded() + } + return this.totalBonded + } + + async getLivepeerDefaultConstants() { + if (!this.defaultConstants) { + this.defaultConstants = await this.source.getLivepeerDefaultConstants() + } + return this.defaultConstants + } + + async getLatestBlock() { + return await this.source.getLatestBlock() + } + + async getLivepeerRoundProgress() { + const [currentRoundInfo, roundLength, latestBlock] = await Promise.all([ + this.getCurrentRoundInfo(), + this.getRoundLength(), + this.getLatestBlock() + ]) + + const { id, initialized, lastInitializedRound, length, startBlock } = currentRoundInfo + const { number } = latestBlock + const nextRoundStartBlock = MathBN.add(startBlock, length) + + const nextRoundNum = MathBN.add(id, '1') + const blocksUntilNextRound = MathBN.sub(nextRoundStartBlock - number) + + return { + roundId: id, + isInitialized: initialized, + lastInitializedRound: lastInitializedRound, + length: length, + startBlock: startBlock, + blocksUntilNextRound: blocksUntilNextRound, + nextRoundStartBlock: nextRoundStartBlock, + roundLength: roundLength, + nextRoundNum: nextRoundNum, + progress: length > 0 ? (blocksUntilNextRound * 100) / length : 0 + } + } + + // Returns the amount of minted tokens for the next round (inflation * totalSupply) + async getMintedTokensForNextRound() { + let [nextInflation, totalSupply] = await Promise.all([ + this.getNextRoundInflation(), + this.getTokenTotalSupply() + ]) + const mintedTokens = MathBN.mul(totalSupply, nextInflation) + return tokenAmountInUnits(mintedTokens) + } + + // Returns the inflation as a ratio for the next round, the value should be divided by 1.000.000 in order to make it a ratio + async getNextRoundInflation() { + let [ + inflationRate, + inflationChange, + targetBondingRate, + totalBonded, + totalSupply + ] = await Promise.all([ + this.getInflationRate(), + this.getInflationChange(), + this.getTargetBondingRate(), + this.getTotalBonded(), + this.getTokenTotalSupply() + ]) + return calculateNextRoundInflationRatio( + inflationRate, + inflationChange, + targetBondingRate, + totalBonded, + totalSupply + ) + } +} + +module.exports = { + getProtocolService +} diff --git a/server/subscriber/subscriber.controller.js b/server/subscriber/subscriber.controller.js index dfe4384..ecf607a 100644 --- a/server/subscriber/subscriber.controller.js +++ b/server/subscriber/subscriber.controller.js @@ -1,19 +1,14 @@ +const { getDelegatorService } = require('../helpers/services/delegatorService') +const { getProtocolService } = require('../helpers/services/protocolService') +const { getDelegateService } = require('../helpers/services/delegateService') + const APIError = require('../helpers/APIError') const httpStatus = require('http-status') const Subscriber = require('./subscriber.model') const Earning = require('../earning/earning.model') -const { - getLivepeerDelegatorAccount, - getLivepeerCurrentRound, - getLivepeerDelegatorTokenBalance, - getLivepeerTranscoderAccount, - getLivepeerCurrentRoundInfo, - getLivepeerDefaultConstants -} = require('../helpers/livepeerAPI') const { fromBaseUnit, formatPercentage, - MathBN, getDelegatorRoundsUntilUnbonded } = require('../helpers/utils') const promiseRetry = require('promise-retry') @@ -76,14 +71,17 @@ const create = async (req, res, next) => { // Create earning Earning.save(savedSubscriber) + const delegatorService = getDelegatorService() + const protocolService = getProtocolService() + const delegateService = getDelegateService() // Send email notification let [delegator, constants, currentRoundInfo] = await Promise.all([ - getLivepeerDelegatorAccount(address), - getLivepeerDefaultConstants(), - getLivepeerCurrentRoundInfo() + delegatorService.getDelegatorAccount(address), + protocolService.getLivepeerDefaultConstants(), + protocolService.getCurrentRoundInfo() ]) - let transcoderAccount = await getLivepeerTranscoderAccount(delegator.delegateAddress) + let transcoderAccount = await delegateService.getDelegate(delegator.delegateAddress) // Detect role let data = { @@ -222,18 +220,21 @@ const summary = async (req, res, next) => { try { const { addressWithoutSubscriber = null } = req.params + const delegatorService = getDelegatorService() + const protocolService = getProtocolService() + const delegateService = getDelegateService() // Get delegator with promise retry, because infura let [delegator, balance, constants, currentRoundInfo] = await promiseRetry(retry => { return Promise.all([ - getLivepeerDelegatorAccount(addressWithoutSubscriber), - getLivepeerDelegatorTokenBalance(addressWithoutSubscriber), - getLivepeerDefaultConstants(), - getLivepeerCurrentRoundInfo() + delegatorService.getDelegatorAccount(addressWithoutSubscriber), + delegatorService.getDelegatorTokenBalance(addressWithoutSubscriber), + protocolService.getLivepeerDefaultConstants(), + protocolService.getCurrentRoundInfo() ]).catch(err => retry()) }) let [transcoderAccount] = await promiseRetry(retry => { - return Promise.all([getLivepeerTranscoderAccount(delegator.delegateAddress)]).catch(err => + return Promise.all([delegateService.getDelegate(delegator.delegateAddress)]).catch(err => retry() ) }) diff --git a/test/server/helpers/delegate.test.js b/test/server/helpers/delegate.test.js index 69a5d09..d8758cf 100644 --- a/test/server/helpers/delegate.test.js +++ b/test/server/helpers/delegate.test.js @@ -2,7 +2,7 @@ const { MathBN } = require('../../../server/helpers/utils') const { tokenAmountInUnits, unitAmountInTokenUnits } = require('../../../server/helpers/utils') -const { getDelegateService } = require('../../../server/helpers/delegateService') +const { getDelegateService } = require('../../../server/helpers/services/delegateService') const { createTranscoder, From bb2e2cb914340ddb7585e09b04b6b73f22d854f4 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Mon, 24 Jun 2019 20:28:12 -0300 Subject: [PATCH 11/20] Adds babel plugin for class properties --- .babelrc | 3 + package-lock.json | 179 ++++++++++++++++++++ package.json | 1 + server/helpers/services/delegateService.js | 12 +- server/helpers/services/delegatorService.js | 6 +- server/helpers/services/protocolService.js | 30 ++-- 6 files changed, 207 insertions(+), 24 deletions(-) create mode 100644 .babelrc diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..84ed5f1 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "plugins": ["@babel/plugin-proposal-class-properties"] +} diff --git a/package-lock.json b/package-lock.json index 592e202..8da76d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,48 @@ } } }, + "@babel/helper-create-class-features-plugin": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.4.4.tgz", + "integrity": "sha512-UbBHIa2qeAGgyiNR9RszVF7bUHEdgS4JAUNT8SiqrAN6YJVxlOxeLr5pBzb5kan302dejJ9nla4RyKcR1XT6XA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.4.4", + "@babel/helper-split-export-declaration": "^7.4.4" + }, + "dependencies": { + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", @@ -54,6 +96,133 @@ "@babel/types": "^7.0.0" } }, + "@babel/helper-member-expression-to-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", + "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + }, + "dependencies": { + "@babel/generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/parser": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "dev": true + }, + "@babel/traverse": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "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" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, "@babel/helper-split-export-declaration": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", @@ -123,6 +292,16 @@ "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", "dev": true }, + "@babel/plugin-proposal-class-properties": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.4.tgz", + "integrity": "sha512-WjKTI8g8d5w1Bc9zgwSz2nfrsNQsXcCf9J9cdCvrJV6RF56yztwm4TmJC0MgJ9tvwO9gUA/mcYe89bLdGfiXFg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/polyfill": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz", diff --git a/package.json b/package.json index 8355c67..182a63b 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "winston": "2.4.1" }, "devDependencies": { + "@babel/plugin-proposal-class-properties": "^7.4.4", "babel-eslint": "^10.0.1", "chai": "4.1.2", "coveralls": "^3.0.2", diff --git a/server/helpers/services/delegateService.js b/server/helpers/services/delegateService.js index 0d83ef5..fa87247 100644 --- a/server/helpers/services/delegateService.js +++ b/server/helpers/services/delegateService.js @@ -25,7 +25,7 @@ class DelegateService { } // Returns the delegate summary plus the missed reward calls - async getDelegate(delegateAddress) { + getDelegate = async delegateAddress => { const { getDelegateSummary } = this.source const summary = await getDelegateSummary(delegateAddress) const last30MissedRewardCalls = await this.getMissedRewardCalls(delegateAddress) @@ -39,7 +39,7 @@ class DelegateService { } // Receives a delegateAddress and returns the TOTAL reward (protocol reward, no the reward cut) of that delegate for the next round - async getDelegateProtocolNextReward(delegateAddress) { + getDelegateProtocolNextReward = async delegateAddress => { const { getDelegateSummary } = this.source const protocolService = getProtocolService() const { getMintedTokensForNextRound, getTotalBonded } = protocolService @@ -61,7 +61,7 @@ class DelegateService { } // Receives a delegateAddress and returns the REAL reward of the delegate (nextReward*rewardCut) - async getDelegateNextReward(delegateAddress) { + getDelegateNextReward = async delegateAddress => { const { getDelegateSummary } = this.source // DelegateReward = DelegateProtocolNextReward * rewardCut let [summary, protocolNextReward] = await promiseRetry(retry => { @@ -77,7 +77,7 @@ class DelegateService { } // For a given delegateAddress return the next reward that will be distributed towards delegators - async getDelegateRewardToDelegators(delegateAddress) { + getDelegateRewardToDelegators = async delegateAddress => { const { getDelegateSummary } = this.source // FORMULA: DelegateRewardToDelegators = DelegateProtocolNextReward - DelegateProtocolNextReward * rewardCut let [summary, protocolNextReward] = await promiseRetry(retry => { @@ -94,7 +94,7 @@ class DelegateService { } // For a given delegatorAddress, returns the next round reward if exists - async getDelegatorNextReturn(delegatorAddress) { + getDelegatorNextReturn = async delegatorAddress => { const protocolService = getProtocolService() const { getLivepeerDelegatorAccount } = protocolService const { getDelegateTotalStake } = this.source @@ -114,7 +114,7 @@ class DelegateService { return MathBN.mul(rewardToDelegators, delegatorParticipationInTotalStake) } - async getMissedRewardCalls(delegateAddress) { + getMissedRewardCalls = async delegateAddress => { const { getDelegateRewards } = this.source const protocolService = getProtocolService() const { getCurrentRound } = protocolService diff --git a/server/helpers/services/delegatorService.js b/server/helpers/services/delegatorService.js index c23f345..a36f942 100644 --- a/server/helpers/services/delegatorService.js +++ b/server/helpers/services/delegatorService.js @@ -14,17 +14,17 @@ class DelegatorService { this.source = source } - async getDelegatorAccount(address) { + getDelegatorAccount = async address => { const { getLivepeerDelegatorAccount } = this.source return await getLivepeerDelegatorAccount(address) } - async getDelegatorTokenBalance(address) { + getDelegatorTokenBalance = async address => { const { getLivepeerDelegatorTokenBalance } = this.source return await getLivepeerDelegatorTokenBalance(address) } - async getLivepeerDelegatorStake(address) { + getLivepeerDelegatorStake = async address => { const { getLivepeerDelegatorStake } = this.source return await getLivepeerDelegatorStake(address) } diff --git a/server/helpers/services/protocolService.js b/server/helpers/services/protocolService.js index b09e299..af5156b 100644 --- a/server/helpers/services/protocolService.js +++ b/server/helpers/services/protocolService.js @@ -44,7 +44,7 @@ class ProtocolService { }, CACHE_UPDATE_INTERVAL) } - async getTokenTotalSupply() { + getTokenTotalSupply = async () => { if (!this.totalTokenSupply) { this.totalTokenSupply = await this.source.getTokenTotalSupply() } @@ -52,7 +52,7 @@ class ProtocolService { } // Returns the inflation of the current round, the value should be divided by 1.000.000 in order to make it a ratio - async getInflationRate() { + getInflationRate = async () => { if (!this.inflationRate) { const inflation = await this.source.getInflation() this.inflationRate = MathBN.div(inflation, PROTOCOL_DIVISION_BASE) @@ -61,7 +61,7 @@ class ProtocolService { } // Returns the change of inflation for the next round, the value should be divided by 1.000.000 in order to make it a ratio - async getInflationChange() { + getInflationChange = async () => { if (!this.inflationChange) { const inflationChange = await this.source.getInflationChange() this.inflationChange = MathBN.div(inflationChange, PROTOCOL_DIVISION_BASE) @@ -69,32 +69,32 @@ class ProtocolService { return this.inflationChange } - async getLastInitializedRound() { + getLastInitializedRound = async () => { if (!this.lastInitializedRound) { this.lastInitializedRound = await this.source.getLastInitializedRound() } return this.lastInitializedRound } - async getCurrentRoundInfo() { + getCurrentRoundInfo = async () => { if (!this.currentRoundInfo) { this.currentRoundInfo = await this.source.getLivepeerCurrentRoundInfo() } return this.currentRoundInfo } - async getRoundLength() { + getRoundLength = async () => { if (!this.currentRoundLenght) { this.currentRoundLenght = await this.source.getRoundLength() } } - async getRoundsPerYear() { + getRoundsPerYear = async () => { if (!this.roundsPerYear) { this.roundsPerYear = await this.source.getRoundsPerYear() } } - async getCurrentRound() { + getCurrentRound = async () => { if (!this.currentRound) { this.currentRound = await this.source.getCurrentRound() } @@ -102,7 +102,7 @@ class ProtocolService { } // Returns the targetBondingRate, the value should be divided by 1.000.000 in order to make it a ratio - async getTargetBondingRate() { + getTargetBondingRate = async () => { if (!this.targetBondingRate) { const target = await this.source.getTargetBondingRate() this.targetBondingRate = MathBN.div(target, PROTOCOL_DIVISION_BASE) @@ -111,25 +111,25 @@ class ProtocolService { } // Returns the total amount of tokens bonded in the protocol - async getTotalBonded() { + getTotalBonded = async () => { if (!this.totalBonded) { this.totalBonded = await this.source.getTotalBonded() } return this.totalBonded } - async getLivepeerDefaultConstants() { + getLivepeerDefaultConstants = async () => { if (!this.defaultConstants) { this.defaultConstants = await this.source.getLivepeerDefaultConstants() } return this.defaultConstants } - async getLatestBlock() { + getLatestBlock = async () => { return await this.source.getLatestBlock() } - async getLivepeerRoundProgress() { + getLivepeerRoundProgress = async () => { const [currentRoundInfo, roundLength, latestBlock] = await Promise.all([ this.getCurrentRoundInfo(), this.getRoundLength(), @@ -158,7 +158,7 @@ class ProtocolService { } // Returns the amount of minted tokens for the next round (inflation * totalSupply) - async getMintedTokensForNextRound() { + getMintedTokensForNextRound = async () => { let [nextInflation, totalSupply] = await Promise.all([ this.getNextRoundInflation(), this.getTokenTotalSupply() @@ -168,7 +168,7 @@ class ProtocolService { } // Returns the inflation as a ratio for the next round, the value should be divided by 1.000.000 in order to make it a ratio - async getNextRoundInflation() { + getNextRoundInflation = async () => { let [ inflationRate, inflationChange, From 44883c49dbe29a3cb9ae1d70de1fdf5bc54f1560 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Mon, 24 Jun 2019 20:45:21 -0300 Subject: [PATCH 12/20] Adds babel-node --- .babelrc | 1 + package-lock.json | 1658 +++++++++++++++++++++++++++++++++++++++++---- package.json | 7 +- 3 files changed, 1545 insertions(+), 121 deletions(-) diff --git a/.babelrc b/.babelrc index 84ed5f1..644dde9 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,4 @@ { + "presets": ["@babel/preset-env"], "plugins": ["@babel/plugin-proposal-class-properties"] } diff --git a/package-lock.json b/package-lock.json index 8da76d8..a0830f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,24 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/cli": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.4.4.tgz", + "integrity": "sha512-XGr5YjQSjgTa6OzQZY57FAJsdeVSAKR/u/KA5exWIz66IKtv/zXtHy+fIZcMry/EgYegwuHE7vzGnrFhjdIAsQ==", + "dev": true, + "requires": { + "chokidar": "^2.0.4", + "commander": "^2.8.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.11", + "mkdirp": "^0.5.1", + "output-file-sync": "^2.0.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + } + }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", @@ -13,41 +31,41 @@ "@babel/highlight": "^7.0.0" } }, - "@babel/generator": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz", - "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==", - "dev": true, - "requires": { - "@babel/types": "^7.2.2", - "jsesc": "^2.5.1", - "lodash": "^4.17.10", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.4.4.tgz", - "integrity": "sha512-UbBHIa2qeAGgyiNR9RszVF7bUHEdgS4JAUNT8SiqrAN6YJVxlOxeLr5pBzb5kan302dejJ9nla4RyKcR1XT6XA==", + "@babel/core": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", + "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", - "@babel/helper-split-export-declaration": "^7.4.4" + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helpers": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.5", + "@babel/types": "^7.4.4", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" }, "dependencies": { + "@babel/generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, "@babel/helper-split-export-declaration": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", @@ -57,6 +75,40 @@ "@babel/types": "^7.4.4" } }, + "@babel/parser": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "dev": true + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + } + }, "@babel/types": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", @@ -68,6 +120,33 @@ "to-fast-properties": "^2.0.0" } }, + "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" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -76,58 +155,53 @@ } } }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "@babel/generator": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz", + "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.2.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + } } }, - "@babel/helper-member-expression-to-functions": { + "@babel/helper-annotate-as-pure": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", "dev": true, "requires": { "@babel/types": "^7.0.0" } }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", "dev": true, "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", "@babel/types": "^7.0.0" } }, - "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", - "dev": true - }, - "@babel/helper-replace-supers": { + "@babel/helper-call-delegate": { "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", - "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", + "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-hoist-variables": "^7.4.4", "@babel/traverse": "^7.4.4", "@babel/types": "^7.4.4" }, @@ -223,85 +297,1008 @@ } } }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", - "dev": true, - "requires": { - "@babel/types": "^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==", + "@babel/helper-create-class-features-plugin": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.4.4.tgz", + "integrity": "sha512-UbBHIa2qeAGgyiNR9RszVF7bUHEdgS4JAUNT8SiqrAN6YJVxlOxeLr5pBzb5kan302dejJ9nla4RyKcR1XT6XA==", "dev": true, "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.4.4", + "@babel/helper-split-export-declaration": "^7.4.4" }, "dependencies": { - "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==", + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "@babel/types": "^7.4.4" } }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + } + } + }, + "@babel/helper-define-map": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", + "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.4.4", + "lodash": "^4.17.11" + }, + "dependencies": { + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true } } }, - "@babel/parser": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", - "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", - "dev": true + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", + "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", + "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.4.4", + "lodash": "^4.17.11" + }, + "dependencies": { + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/parser": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "dev": true + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", + "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", + "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + }, + "dependencies": { + "@babel/generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/parser": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "dev": true + }, + "@babel/traverse": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "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" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-wrap-function": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + } + }, + "@babel/helpers": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + }, + "dependencies": { + "@babel/generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/parser": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "dev": true + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "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" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@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" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "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 + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/node": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.4.5.tgz", + "integrity": "sha512-nDXPT0KwYMycDHhFG9wKlkipCR+iXzzoX9bD2aF2UABLhQ13AKhNi5Y61W8ASGPPll/7p9GrHesmlOgTUJVcfw==", + "dev": true, + "requires": { + "@babel/polyfill": "^7.0.0", + "@babel/register": "^7.0.0", + "commander": "^2.8.1", + "lodash": "^4.17.11", + "node-environment-flags": "^1.0.5", + "v8flags": "^3.1.1" + } + }, + "@babel/parser": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", + "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.4.tgz", + "integrity": "sha512-WjKTI8g8d5w1Bc9zgwSz2nfrsNQsXcCf9J9cdCvrJV6RF56yztwm4TmJC0MgJ9tvwO9gUA/mcYe89bLdGfiXFg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", + "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", + "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", + "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", + "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", + "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", + "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", + "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", + "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.11" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", + "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.4.4", + "@babel/helper-split-export-declaration": "^7.4.4", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", + "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", + "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", + "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", + "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", + "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", + "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", + "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", + "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", + "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", + "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", + "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", + "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", + "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", + "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", + "dev": true, + "requires": { + "regexp-tree": "^0.1.6" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", + "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", + "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", + "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.4.4", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", + "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", + "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.0" + } }, - "@babel/plugin-proposal-class-properties": { + "@babel/plugin-transform-reserved-words": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", + "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", + "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", + "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", + "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.4.tgz", - "integrity": "sha512-WjKTI8g8d5w1Bc9zgwSz2nfrsNQsXcCf9J9cdCvrJV6RF56yztwm4TmJC0MgJ9tvwO9gUA/mcYe89bLdGfiXFg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", + "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", + "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", + "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } + }, "@babel/polyfill": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz", @@ -320,6 +1317,103 @@ } } }, + "@babel/preset-env": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", + "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.4.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.4.4", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.4.4", + "@babel/plugin-transform-classes": "^7.4.4", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.4.4", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-member-expression-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.4.4", + "@babel/plugin-transform-modules-systemjs": "^7.4.4", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", + "@babel/plugin-transform-new-target": "^7.4.4", + "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-parameters": "^7.4.4", + "@babel/plugin-transform-property-literals": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.4.5", + "@babel/plugin-transform-reserved-words": "^7.2.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.4.4", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.5.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/register": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.4.4.tgz", + "integrity": "sha512-sn51H88GRa00+ZoMqCVgOphmswG4b7mhf9VOB0LUBAieykq2GnRFerlN+JQkO/ntT7wz4jaHNSRPg9IdMPEUkA==", + "dev": true, + "requires": { + "core-js": "^3.0.0", + "find-cache-dir": "^2.0.0", + "lodash": "^4.17.11", + "mkdirp": "^0.5.1", + "pirates": "^4.0.0", + "source-map-support": "^0.5.9" + }, + "dependencies": { + "core-js": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", + "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", + "dev": true + } + } + }, "@babel/template": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", @@ -1308,6 +2402,17 @@ "safe-buffer": "^5.0.1" } }, + "browserslist": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", + "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000975", + "electron-to-chromium": "^1.3.164", + "node-releases": "^1.1.23" + } + }, "bson": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.0.tgz", @@ -1393,6 +2498,12 @@ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" }, + "caniuse-lite": { + "version": "1.0.30000976", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000976.tgz", + "integrity": "sha512-tleNB1IwPRqZiod6nUNum63xQCMN96BUO2JTeiwuRM7p9d616EHsMBjBWJMudX39qCaPuWY8KEWzMZq7A9XQMQ==", + "dev": true + }, "capture-stack-trace": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", @@ -1557,8 +2668,13 @@ "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "optional": true + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true }, "component-emitter": { "version": "1.2.1", @@ -1632,6 +2748,15 @@ "integrity": "sha1-XblXOdbCEqy+e29lahG5QLqmiUY=", "dev": true }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", @@ -1667,6 +2792,31 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz", "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==" }, + "core-js-compat": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", + "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", + "dev": true, + "requires": { + "browserslist": "^4.6.2", + "core-js-pure": "3.1.4", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.2.tgz", + "integrity": "sha512-z4PqiCpomGtWj8633oeAdXm1Kn1W++3T8epkZYnwiVgIYIJ0QHszhInYSJTYxebByQH7KVCEAn8R9duzZW2PhQ==", + "dev": true + } + } + }, + "core-js-pure": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.1.4.tgz", + "integrity": "sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -2007,6 +3157,12 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "electron-to-chromium": { + "version": "1.3.172", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.172.tgz", + "integrity": "sha512-bHgFvYeHBiQNNuY/WvoX37zLosPgMbR8nKU1r4mylHptLvuMMny/KG/L28DTIlcoOCJjMAhEimy3DHDgDayPbg==", + "dev": true + }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -3201,6 +4357,53 @@ } } }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, "find-parent-dir": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", @@ -3302,6 +4505,12 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4171,6 +5380,15 @@ "resolved": "http://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, + "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" + } + }, "host-validation": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/host-validation/-/host-validation-2.0.1.tgz", @@ -4621,6 +5839,12 @@ "path-is-inside": "^1.0.1" } }, + "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=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -4869,6 +6093,12 @@ "topo": "2.x.x" } }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true + }, "js-sha3": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", @@ -4928,6 +6158,15 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -5583,11 +6822,44 @@ "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz", "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-releases": { + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", + "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, "node-telegram-bot-api": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/node-telegram-bot-api/-/node-telegram-bot-api-0.30.0.tgz", @@ -5787,6 +7059,16 @@ "isobject": "^3.0.0" } }, + "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", @@ -5874,6 +7156,17 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "output-file-sync": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz", + "integrity": "sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "is-plain-obj": "^1.1.0", + "mkdirp": "^0.5.1" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -5933,6 +7226,12 @@ "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", @@ -6014,6 +7313,15 @@ "pinkie": "^2.0.0" } }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, "pkg-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", @@ -6083,6 +7391,12 @@ "fast-diff": "^1.1.2" } }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -6246,12 +7560,36 @@ "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz", "integrity": "sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk=" }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, "regenerator-runtime": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==", "dev": true }, + "regenerator-transform": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", + "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -6266,12 +7604,32 @@ "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" }, + "regexp-tree": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", + "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", + "dev": true + }, "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 }, + "regexpu-core": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.0.2", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, "registry-auth-token": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", @@ -6289,6 +7647,29 @@ "rc": "^1.0.1" } }, + "regjsgen": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "dev": true + }, + "regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -7366,6 +8747,34 @@ "debug": "^2.2.0" } }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", + "dev": true + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -7548,6 +8957,15 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, + "v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "validate-commit-msg": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/validate-commit-msg/-/validate-commit-msg-2.14.0.tgz", diff --git a/package.json b/package.json index 182a63b..3c68ae7 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "yarn": ">=1.5.1" }, "scripts": { - "start": "nodemon index.js", + "start": "nodemon --exec babel-node index.js ", + "build": "babel index.js -d dist", "lint": "esw *.js server config --color", "lint:watch": "npm run lint -- --watch", "test": "NODE_ENV=test ./node_modules/.bin/mocha test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server", @@ -71,7 +72,11 @@ "winston": "2.4.1" }, "devDependencies": { + "@babel/cli": "^7.4.4", + "@babel/core": "^7.4.5", + "@babel/node": "^7.4.5", "@babel/plugin-proposal-class-properties": "^7.4.4", + "@babel/preset-env": "^7.4.5", "babel-eslint": "^10.0.1", "chai": "4.1.2", "coveralls": "^3.0.2", From cf456a56da3d0e8e8906355564b5faa8a52ae590 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Tue, 25 Jun 2019 10:15:15 -0300 Subject: [PATCH 13/20] Replaces babel with --harmony flag Fixs imports --- package-lock.json | 1725 ++----------------------------- package.json | 12 +- server/earning/earning.model.js | 2 +- server/helpers/sdk/delegator.js | 1 + 4 files changed, 69 insertions(+), 1671 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0830f6..592e202 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,24 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@babel/cli": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.4.4.tgz", - "integrity": "sha512-XGr5YjQSjgTa6OzQZY57FAJsdeVSAKR/u/KA5exWIz66IKtv/zXtHy+fIZcMry/EgYegwuHE7vzGnrFhjdIAsQ==", - "dev": true, - "requires": { - "chokidar": "^2.0.4", - "commander": "^2.8.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", - "lodash": "^4.17.11", - "mkdirp": "^0.5.1", - "output-file-sync": "^2.0.0", - "slash": "^2.0.0", - "source-map": "^0.5.0" - } - }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", @@ -31,130 +13,6 @@ "@babel/highlight": "^7.0.0" } }, - "@babel/core": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", - "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helpers": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.5", - "@babel/types": "^7.4.4", - "convert-source-map": "^1.1.0", - "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.11", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4", - "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", - "dev": true - }, - "@babel/template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", - "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" - } - }, - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, "@babel/generator": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz", @@ -176,209 +34,6 @@ } } }, - "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-call-delegate": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", - "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - }, - "dependencies": { - "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4", - "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", - "dev": true - }, - "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" - } - }, - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.4.4.tgz", - "integrity": "sha512-UbBHIa2qeAGgyiNR9RszVF7bUHEdgS4JAUNT8SiqrAN6YJVxlOxeLr5pBzb5kan302dejJ9nla4RyKcR1XT6XA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", - "@babel/helper-split-export-declaration": "^7.4.4" - }, - "dependencies": { - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-define-map": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", - "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" - }, - "dependencies": { - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", @@ -396,1020 +51,92 @@ "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", - "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - }, - "dependencies": { - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", - "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/template": "^7.4.4", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" - }, - "dependencies": { - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", - "dev": true - }, - "@babel/template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", - "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", - "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-replace-supers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", - "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - }, - "dependencies": { - "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4", - "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", - "dev": true - }, - "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" - } - }, - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-simple-access": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-wrap-function": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", - "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.2.0" - } - }, - "@babel/helpers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", - "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", - "dev": true, - "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - }, - "dependencies": { - "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4", - "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", - "dev": true - }, - "@babel/template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", - "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" - } - }, - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@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" - }, - "dependencies": { - "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==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/node": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.4.5.tgz", - "integrity": "sha512-nDXPT0KwYMycDHhFG9wKlkipCR+iXzzoX9bD2aF2UABLhQ13AKhNi5Y61W8ASGPPll/7p9GrHesmlOgTUJVcfw==", - "dev": true, - "requires": { - "@babel/polyfill": "^7.0.0", - "@babel/register": "^7.0.0", - "commander": "^2.8.1", - "lodash": "^4.17.11", - "node-environment-flags": "^1.0.5", - "v8flags": "^3.1.1" - } - }, - "@babel/parser": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", - "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", - "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.4.tgz", - "integrity": "sha512-WjKTI8g8d5w1Bc9zgwSz2nfrsNQsXcCf9J9cdCvrJV6RF56yztwm4TmJC0MgJ9tvwO9gUA/mcYe89bLdGfiXFg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", - "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", - "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", - "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", - "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.11" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", - "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", - "@babel/helper-split-export-declaration": "^7.4.4", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", - "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", - "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", - "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", - "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", - "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", - "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", - "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", - "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", - "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", - "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", - "dev": true, - "requires": { - "regexp-tree": "^0.1.6" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", - "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", - "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", - "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.0" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", - "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", - "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", - "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "@babel/types": "^7.0.0" } }, - "@babel/polyfill": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz", - "integrity": "sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg==", + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", "dev": true, "requires": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.2" - }, - "dependencies": { - "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", - "dev": true - } + "@babel/types": "^7.0.0" } }, - "@babel/preset-env": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", - "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", + "@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": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.4", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.4", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.4", - "@babel/plugin-transform-classes": "^7.4.4", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.2.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.4", - "@babel/plugin-transform-modules-systemjs": "^7.4.4", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "browserslist": "^4.6.0", - "core-js-compat": "^3.1.1", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.5.0" + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" }, "dependencies": { - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "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==", "dev": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" + "color-convert": "^1.9.0" } }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "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 + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, - "@babel/register": { + "@babel/parser": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", + "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", + "dev": true + }, + "@babel/polyfill": { "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.4.4.tgz", - "integrity": "sha512-sn51H88GRa00+ZoMqCVgOphmswG4b7mhf9VOB0LUBAieykq2GnRFerlN+JQkO/ntT7wz4jaHNSRPg9IdMPEUkA==", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz", + "integrity": "sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg==", "dev": true, "requires": { - "core-js": "^3.0.0", - "find-cache-dir": "^2.0.0", - "lodash": "^4.17.11", - "mkdirp": "^0.5.1", - "pirates": "^4.0.0", - "source-map-support": "^0.5.9" + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.2" }, "dependencies": { "core-js": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", - "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", "dev": true } } @@ -2402,17 +1129,6 @@ "safe-buffer": "^5.0.1" } }, - "browserslist": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", - "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000975", - "electron-to-chromium": "^1.3.164", - "node-releases": "^1.1.23" - } - }, "bson": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.0.tgz", @@ -2498,12 +1214,6 @@ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" }, - "caniuse-lite": { - "version": "1.0.30000976", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000976.tgz", - "integrity": "sha512-tleNB1IwPRqZiod6nUNum63xQCMN96BUO2JTeiwuRM7p9d616EHsMBjBWJMudX39qCaPuWY8KEWzMZq7A9XQMQ==", - "dev": true - }, "capture-stack-trace": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", @@ -2668,13 +1378,8 @@ "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "optional": true }, "component-emitter": { "version": "1.2.1", @@ -2748,15 +1453,6 @@ "integrity": "sha1-XblXOdbCEqy+e29lahG5QLqmiUY=", "dev": true }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", @@ -2792,31 +1488,6 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz", "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==" }, - "core-js-compat": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", - "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", - "dev": true, - "requires": { - "browserslist": "^4.6.2", - "core-js-pure": "3.1.4", - "semver": "^6.1.1" - }, - "dependencies": { - "semver": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.2.tgz", - "integrity": "sha512-z4PqiCpomGtWj8633oeAdXm1Kn1W++3T8epkZYnwiVgIYIJ0QHszhInYSJTYxebByQH7KVCEAn8R9duzZW2PhQ==", - "dev": true - } - } - }, - "core-js-pure": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.1.4.tgz", - "integrity": "sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -3157,12 +1828,6 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, - "electron-to-chromium": { - "version": "1.3.172", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.172.tgz", - "integrity": "sha512-bHgFvYeHBiQNNuY/WvoX37zLosPgMbR8nKU1r4mylHptLvuMMny/KG/L28DTIlcoOCJjMAhEimy3DHDgDayPbg==", - "dev": true - }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -4357,53 +3022,6 @@ } } }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - } - } - }, "find-parent-dir": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", @@ -4505,12 +3123,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5380,15 +3992,6 @@ "resolved": "http://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, - "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" - } - }, "host-validation": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/host-validation/-/host-validation-2.0.1.tgz", @@ -5839,12 +4442,6 @@ "path-is-inside": "^1.0.1" } }, - "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=", - "dev": true - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -6093,12 +4690,6 @@ "topo": "2.x.x" } }, - "js-levenshtein": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", - "dev": true - }, "js-sha3": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", @@ -6158,15 +4749,6 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, - "json5": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", - "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -6822,44 +5404,11 @@ "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz", "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true - } - } - }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, - "node-releases": { - "version": "1.1.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", - "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } - }, "node-telegram-bot-api": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/node-telegram-bot-api/-/node-telegram-bot-api-0.30.0.tgz", @@ -7059,16 +5608,6 @@ "isobject": "^3.0.0" } }, - "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", @@ -7156,17 +5695,6 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "output-file-sync": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz", - "integrity": "sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "is-plain-obj": "^1.1.0", - "mkdirp": "^0.5.1" - } - }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -7226,12 +5754,6 @@ "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", @@ -7313,15 +5835,6 @@ "pinkie": "^2.0.0" } }, - "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } - }, "pkg-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", @@ -7391,12 +5904,6 @@ "fast-diff": "^1.1.2" } }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -7560,36 +6067,12 @@ "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz", "integrity": "sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk=" }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, "regenerator-runtime": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==", "dev": true }, - "regenerator-transform": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", - "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -7604,32 +6087,12 @@ "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" }, - "regexp-tree": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", - "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", - "dev": true - }, "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 }, - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, "registry-auth-token": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", @@ -7647,29 +6110,6 @@ "rc": "^1.0.1" } }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -8747,34 +7187,6 @@ "debug": "^2.2.0" } }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", - "dev": true - }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -8957,15 +7369,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, - "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "validate-commit-msg": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/validate-commit-msg/-/validate-commit-msg-2.14.0.tgz", diff --git a/package.json b/package.json index 3c68ae7..5ae5b5b 100644 --- a/package.json +++ b/package.json @@ -6,16 +6,15 @@ "main": "index.js", "private": false, "engines": { - "node": ">=8.10.0", + "node": ">=10.16.0", "npm": ">=5.6.0", "yarn": ">=1.5.1" }, "scripts": { - "start": "nodemon --exec babel-node index.js ", - "build": "babel index.js -d dist", + "start": "nodemon --harmony index.js ", "lint": "esw *.js server config --color", "lint:watch": "npm run lint -- --watch", - "test": "NODE_ENV=test ./node_modules/.bin/mocha test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server", + "test": "NODE_ENV=test ./node_modules/.bin/mocha test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server --harmony", "test:watch": "npm run test -- --watch", "test:coverage": "NODE_ENV=test ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server", "test:check-coverage": "npm run test:coverage && istanbul check-coverage", @@ -72,11 +71,6 @@ "winston": "2.4.1" }, "devDependencies": { - "@babel/cli": "^7.4.4", - "@babel/core": "^7.4.5", - "@babel/node": "^7.4.5", - "@babel/plugin-proposal-class-properties": "^7.4.4", - "@babel/preset-env": "^7.4.5", "babel-eslint": "^10.0.1", "chai": "4.1.2", "coveralls": "^3.0.2", diff --git a/server/earning/earning.model.js b/server/earning/earning.model.js index 705d61c..9345a59 100644 --- a/server/earning/earning.model.js +++ b/server/earning/earning.model.js @@ -67,7 +67,7 @@ EarningSchema.statics = { const protocolService = getProtocolService() let [delegator, currentRoundInfo] = await Promise.all([ delegatorService.getDelegatorAccount(address), - protocolService.getLivepeerCurrentRoundInfo() + protocolService.getCurrentRoundInfo() ]) const { lastClaimRound, pendingStake, bondedAmount } = delegator diff --git a/server/helpers/sdk/delegator.js b/server/helpers/sdk/delegator.js index daf8683..8b20c70 100644 --- a/server/helpers/sdk/delegator.js +++ b/server/helpers/sdk/delegator.js @@ -1,4 +1,5 @@ const LivepeerSDK = require('@mariano-aguero/sdk') +const { MathBN } = require('../utils') const getLivepeerDelegatorAccount = async address => { if (!address) { return null From 2c539d88c9a5c360c06f06fce0b5dac7aed4b7ea Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Tue, 25 Jun 2019 11:21:34 -0300 Subject: [PATCH 14/20] Fixs imports Fixs wrong function calls Updates service dependencies on sendEmailClaimRewardCall.js Remoes promise retry from load subscriber, now should be done on the sdk --- server/helpers/sendEmailClaimRewardCall.js | 24 +++++++++++----------- server/helpers/services/protocolService.js | 2 +- server/subscriber/subscriber.controller.js | 23 ++++++++------------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/server/helpers/sendEmailClaimRewardCall.js b/server/helpers/sendEmailClaimRewardCall.js index 4e7a38a..d314fb5 100644 --- a/server/helpers/sendEmailClaimRewardCall.js +++ b/server/helpers/sendEmailClaimRewardCall.js @@ -1,16 +1,13 @@ +const { getDelegatorService } = require('./services/delegatorService') +const { getProtocolService } = require('./services/protocolService') +const { getDelegateService } = require('./services/delegateService') + const sgMail = require('@sendgrid/mail') const promiseRetry = require('promise-retry') const config = require('../../config/config') const moment = require('moment') const Earning = require('../earning/earning.model') -const { - getLivepeerDelegatorAccount, - getLivepeerTranscoderAccount, - getLivepeerCurrentRound, - getLivepeerDefaultConstants, - getLivepeerCurrentRoundInfo -} = require('./livepeerAPI') const { truncateStringInTheMiddle, getEarningParams, @@ -81,10 +78,13 @@ const sendEmailClaimRewardCall = async data => { const sendNotificationEmail = async (subscriber, createEarningOnSend = false) => { try { + const delegatorService = getDelegatorService() + const protocolService = getProtocolService() + const delegateService = getDelegateService() let [delegator, constants] = await promiseRetry(async retry => { return Promise.all([ - getLivepeerDelegatorAccount(subscriber.address), - getLivepeerDefaultConstants() + delegatorService.getDelegatorAccount(subscriber.address), + protocolService.getLivepeerDefaultConstants() ]).catch(err => retry()) }) @@ -96,8 +96,8 @@ const sendNotificationEmail = async (subscriber, createEarningOnSend = false) => // Check call reward let [transcoderAccount, currentRound] = await promiseRetry(async retry => { return Promise.all([ - getLivepeerTranscoderAccount(delegator.delegateAddress), - getLivepeerCurrentRound() + delegateService.getDelegate(delegator.delegateAddress), + protocolService.getCurrentRound() ]).catch(err => retry()) }) @@ -149,7 +149,7 @@ const sendNotificationEmail = async (subscriber, createEarningOnSend = false) => templateId = sendgridTemplateIdClaimRewardUnbondingState const [currentRoundInfo] = await promiseRetry(retry => { - return Promise.all([getLivepeerCurrentRoundInfo()]).catch(err => retry()) + return Promise.all([protocolService.getLivepeerCurrentRoundInfo()]).catch(err => retry()) }) const roundsUntilUnbonded = getDelegatorRoundsUntilUnbonded({ diff --git a/server/helpers/services/protocolService.js b/server/helpers/services/protocolService.js index af5156b..3895d81 100644 --- a/server/helpers/services/protocolService.js +++ b/server/helpers/services/protocolService.js @@ -96,7 +96,7 @@ class ProtocolService { } getCurrentRound = async () => { if (!this.currentRound) { - this.currentRound = await this.source.getCurrentRound() + this.currentRound = await this.source.getLivepeerCurrentRound() } return this.currentRound } diff --git a/server/subscriber/subscriber.controller.js b/server/subscriber/subscriber.controller.js index ecf607a..150d2a9 100644 --- a/server/subscriber/subscriber.controller.js +++ b/server/subscriber/subscriber.controller.js @@ -11,7 +11,6 @@ const { formatPercentage, getDelegatorRoundsUntilUnbonded } = require('../helpers/utils') -const promiseRetry = require('promise-retry') /** * Load subscriber and append to req. @@ -223,21 +222,15 @@ const summary = async (req, res, next) => { const delegatorService = getDelegatorService() const protocolService = getProtocolService() const delegateService = getDelegateService() - // Get delegator with promise retry, because infura - let [delegator, balance, constants, currentRoundInfo] = await promiseRetry(retry => { - return Promise.all([ - delegatorService.getDelegatorAccount(addressWithoutSubscriber), - delegatorService.getDelegatorTokenBalance(addressWithoutSubscriber), - protocolService.getLivepeerDefaultConstants(), - protocolService.getCurrentRoundInfo() - ]).catch(err => retry()) - }) - let [transcoderAccount] = await promiseRetry(retry => { - return Promise.all([delegateService.getDelegate(delegator.delegateAddress)]).catch(err => - retry() - ) - }) + let [delegator, balance, constants, currentRoundInfo] = Promise.all([ + delegatorService.getDelegatorAccount(addressWithoutSubscriber), + delegatorService.getDelegatorTokenBalance(addressWithoutSubscriber), + protocolService.getLivepeerDefaultConstants(), + protocolService.getCurrentRoundInfo() + ]) + + let [transcoderAccount] = await delegateService.getDelegate(delegator.delegateAddress) // Detect role let data = { From c2509c992ac11b6f87b0643a875eac0e2022cb02 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Tue, 25 Jun 2019 11:34:44 -0300 Subject: [PATCH 15/20] Minor fixes --- server/subscriber/subscriber.controller.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/subscriber/subscriber.controller.js b/server/subscriber/subscriber.controller.js index 150d2a9..f13fb9a 100644 --- a/server/subscriber/subscriber.controller.js +++ b/server/subscriber/subscriber.controller.js @@ -223,14 +223,14 @@ const summary = async (req, res, next) => { const protocolService = getProtocolService() const delegateService = getDelegateService() - let [delegator, balance, constants, currentRoundInfo] = Promise.all([ + let [delegator, balance, constants, currentRoundInfo] = await Promise.all([ delegatorService.getDelegatorAccount(addressWithoutSubscriber), delegatorService.getDelegatorTokenBalance(addressWithoutSubscriber), protocolService.getLivepeerDefaultConstants(), protocolService.getCurrentRoundInfo() ]) - let [transcoderAccount] = await delegateService.getDelegate(delegator.delegateAddress) + let transcoderAccount = await delegateService.getDelegate(delegator.delegateAddress) // Detect role let data = { @@ -283,6 +283,7 @@ const summary = async (req, res, next) => { res.json(data) } catch (error) { + console.error('eee ', error) next(error) } } From f76f875f5661dd1fb0e296ceb968d31ab7c7f540 Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Tue, 25 Jun 2019 12:08:12 -0300 Subject: [PATCH 16/20] Adds travis_wait --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 026c669..a489574 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,6 @@ cache: git: depth: 3 script: - - npm run test:coverage + - travis_wait npm run test:coverage after_script: - - npm run report-coverage + - travis_wait npm run report-coverage From f054990fb141793bdec71c3337732162c442b4da Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Tue, 25 Jun 2019 12:35:41 -0300 Subject: [PATCH 17/20] Force the tests return exit code after finish Removes travis_wait --- .travis.yml | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index a489574..026c669 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,6 @@ cache: git: depth: 3 script: - - travis_wait npm run test:coverage + - npm run test:coverage after_script: - - travis_wait npm run report-coverage + - npm run report-coverage diff --git a/package.json b/package.json index 5ae5b5b..64a50c6 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,9 @@ "start": "nodemon --harmony index.js ", "lint": "esw *.js server config --color", "lint:watch": "npm run lint -- --watch", - "test": "NODE_ENV=test ./node_modules/.bin/mocha test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server --harmony", + "test": "NODE_ENV=test ./node_modules/.bin/mocha test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server --harmony --exit", "test:watch": "npm run test -- --watch", - "test:coverage": "NODE_ENV=test ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server", + "test:coverage": "NODE_ENV=test ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server --exit", "test:check-coverage": "npm run test:coverage && istanbul check-coverage", "report-coverage": "coveralls < ./coverage/lcov.info" }, From 5aff93aa064f4e24f39a068beb1bfcc2975311fc Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Tue, 25 Jun 2019 16:40:12 -0300 Subject: [PATCH 18/20] Removes old calculations on protocol.js based on rpc response, how they should be done on the protocolService Fixes wrong method name --- server/helpers/sdk/protocol.js | 10 +++------- server/helpers/services/protocolService.js | 3 ++- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/server/helpers/sdk/protocol.js b/server/helpers/sdk/protocol.js index e91c06f..51a1d35 100644 --- a/server/helpers/sdk/protocol.js +++ b/server/helpers/sdk/protocol.js @@ -1,4 +1,3 @@ -const { PROTOCOL_DIVISION_BASE } = require('../../../config/constants') const LivepeerSDK = require('@mariano-aguero/sdk') const getLivepeerCurrentRound = async () => { @@ -33,22 +32,19 @@ const getTokenTotalSupply = async () => { // Returns the inflation of the current round, the value should be divided by 1.000.000 in order to make it a ratio const getInflationRate = async () => { const { rpc } = await LivepeerSDK.default() - const inflation = await rpc.getInflation() - return MathBN.div(inflation, PROTOCOL_DIVISION_BASE) + return await rpc.getInflation() } // Returns the change of inflation for the next round, the value should be divided by 1.000.000 in order to make it a ratio const getInflationChange = async () => { const { rpc } = await LivepeerSDK.default() - const inflationChange = await rpc.getInflationChange() - return MathBN.div(inflationChange, PROTOCOL_DIVISION_BASE) + return await rpc.getInflationChange() } // Returns the targetBondingRate, the value should be divided by 1.000.000 in order to make it a ratio const getTargetBondingRate = async () => { const { rpc } = await LivepeerSDK.default() - const target = await rpc.getTargetBondingRate() - return MathBN.div(target, PROTOCOL_DIVISION_BASE) + return await rpc.getTargetBondingRate() } // Returns the total amount of tokens bonded in the protocol diff --git a/server/helpers/services/protocolService.js b/server/helpers/services/protocolService.js index 3895d81..e5dd395 100644 --- a/server/helpers/services/protocolService.js +++ b/server/helpers/services/protocolService.js @@ -1,6 +1,7 @@ const { calculateNextRoundInflationRatio, tokenAmountInUnits } = require('../utils') const { CACHE_UPDATE_INTERVAL, PROTOCOL_DIVISION_BASE } = require('../../../config/constants') +const { MathBN } = require('../utils') const defaultProtocolSource = require('../sdk/protocol') let protocolServiceInstance @@ -54,7 +55,7 @@ class ProtocolService { // Returns the inflation of the current round, the value should be divided by 1.000.000 in order to make it a ratio getInflationRate = async () => { if (!this.inflationRate) { - const inflation = await this.source.getInflation() + const inflation = await this.source.getInflationRate() this.inflationRate = MathBN.div(inflation, PROTOCOL_DIVISION_BASE) } return this.inflationRate From 62bbb4c3a3318f66c969d07939ac4c9d6ed5cd0f Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Tue, 25 Jun 2019 17:42:09 -0300 Subject: [PATCH 19/20] Fixs getMissedRewardCalls on delegateService.js Adds getDelegateRewards on delegateService.js Adds getDelegateTotalStake on delegateService.js Fixs tests --- server/helpers/services/delegateService.js | 40 ++-- test/{server/helpers => }/delegate.test.js | 240 +++++---------------- 2 files changed, 69 insertions(+), 211 deletions(-) rename test/{server/helpers => }/delegate.test.js (58%) diff --git a/server/helpers/services/delegateService.js b/server/helpers/services/delegateService.js index fa87247..4bb0efc 100644 --- a/server/helpers/services/delegateService.js +++ b/server/helpers/services/delegateService.js @@ -56,7 +56,6 @@ class DelegateService { const { totalStake } = summary // FORMULA: delegateTotalStake / protocolTotalBonded const participationInTotalBondedRatio = MathBN.div(totalStake, totalBondedInProtocol) - return MathBN.mul(mintedTokensForNextRound, participationInTotalBondedRatio) } @@ -93,39 +92,28 @@ class DelegateService { return MathBN.sub(protocolNextReward, rewardToDelegate) } - // For a given delegatorAddress, returns the next round reward if exists - getDelegatorNextReturn = async delegatorAddress => { - const protocolService = getProtocolService() - const { getLivepeerDelegatorAccount } = protocolService - const { getDelegateTotalStake } = this.source - // FORMULA: rewardToDelegators * delegatorParticipationInTotalStake - const delegator = await promiseRetry(retry => { - try { - return getLivepeerDelegatorAccount(delegatorAddress) - } catch (err) { - retry() - } - }) - const { delegateAddress, totalStake } = delegator - const delegateTotalStake = await getDelegateTotalStake(delegateAddress) - // Delegator participation FORMULA: delegatorTotalStake / delegateTotalStake - const delegatorParticipationInTotalStake = MathBN.div(totalStake, delegateTotalStake) - const rewardToDelegators = await this.getDelegateRewardToDelegators(delegateAddress) - return MathBN.mul(rewardToDelegators, delegatorParticipationInTotalStake) - } - getMissedRewardCalls = async delegateAddress => { - const { getDelegateRewards } = this.source const protocolService = getProtocolService() - const { getCurrentRound } = protocolService let missedCalls = 0 - const rewards = await getDelegateRewards(delegateAddress) - const currentRound = await getCurrentRound() + const rewards = await this.getDelegateRewards(delegateAddress) + const currentRound = await protocolService.getCurrentRound() if (rewards) { missedCalls = calculateMissedRewardCalls(rewards, currentRound) } return missedCalls } + + getDelegateRewards = async delegateAddress => { + const { getDelegateRewards } = this.source + const rewards = await getDelegateRewards(delegateAddress) + return rewards + } + + getDelegateTotalStake = async delegateAddress => { + const { getDelegateTotalStake } = this.source + const totalStake = await getDelegateTotalStake(delegateAddress) + return totalStake + } } module.exports = { diff --git a/test/server/helpers/delegate.test.js b/test/delegate.test.js similarity index 58% rename from test/server/helpers/delegate.test.js rename to test/delegate.test.js index d8758cf..149a472 100644 --- a/test/server/helpers/delegate.test.js +++ b/test/delegate.test.js @@ -1,21 +1,21 @@ -const { MathBN } = require('../../../server/helpers/utils') +const { getProtocolService } = require('../server/helpers/services/protocolService') -const { tokenAmountInUnits, unitAmountInTokenUnits } = require('../../../server/helpers/utils') +const { MathBN } = require('../server/helpers/utils') -const { getDelegateService } = require('../../../server/helpers/services/delegateService') +const { tokenAmountInUnits, unitAmountInTokenUnits } = require('../server/helpers/utils') + +const { getDelegateService } = require('../server/helpers/services/delegateService') + +const { createTranscoder, createRewardObject } = require('../server/helpers/test/util') -const { - createTranscoder, - createDelegator, - createRewardObject -} = require('../../../server/helpers/test/util') -const delegatesGraphql = require('../../../server/helpers/graphql/queries/index') -const protocolSdk = require('../../../server/helpers/livepeerAPI') const chai = require('chai') const expect = chai.expect const sinon = require('sinon') +const delegatesGraphql = require('../server/helpers/graphql/queries/delegate') describe('## DelegateService test', () => { + const protocolService = getProtocolService() + const delegateService = getDelegateService(delegatesGraphql) describe('# getDelegate', () => { it('getDelegate should return a delegate with missedRewardCalls', async () => { // given @@ -23,7 +23,6 @@ describe('## DelegateService test', () => { const missedRewardCalls = 0 // stubs the delegateGraphql service const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) // stubs getMissedRewardCalls method const getMissedRewardCallsStub = sinon .stub(delegateService, 'getMissedRewardCalls') @@ -59,11 +58,12 @@ describe('## DelegateService test', () => { delegate.totalStake = unitAmountInTokenUnits(40) const totalBondedStake = unitAmountInTokenUnits(400) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const getMintedTokensForNextRoundStub = sinon - .stub(protocolSdk, 'getMintedTokensForNextRound') + const totalBondedStub = sinon + .stub(protocolService, 'getTotalBonded') + .returns(totalBondedStake) + const mintedTokensStub = sinon + .stub(protocolService, 'getMintedTokensForNextRound') .returns(140) - const getTotalBondedStub = sinon.stub(protocolSdk, 'getTotalBonded').returns(totalBondedStake) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) const rewardExpected = '14' // when @@ -71,13 +71,13 @@ describe('## DelegateService test', () => { // then expect(getSummaryStub.called) - expect(getMintedTokensForNextRoundStub.called) - expect(getTotalBondedStub.called) + expect(totalBondedStub.called) + expect(mintedTokensStub.called) expect(result).equal(rewardExpected) // restore stubs getSummaryStub.restore() - getMintedTokensForNextRoundStub.restore() - getTotalBondedStub.restore() + totalBondedStub.restore() + mintedTokensStub.restore() }) it('100 minted tokens for next round, protocol bondedStake is 1400, the bondedStake of the delegate is 512.4 (36.6% of the totalBonded), result should be 36.6', async () => { // given @@ -85,11 +85,14 @@ describe('## DelegateService test', () => { delegate.totalStake = unitAmountInTokenUnits('512.4') const totalBondedStake = unitAmountInTokenUnits(1400) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const getMintedTokensForNextRoundStub = sinon - .stub(protocolSdk, 'getMintedTokensForNextRound') + const mintedTokensStub = sinon + .stub(protocolService, 'getMintedTokensForNextRound') .returns(100) - const getTotalBondedStub = sinon.stub(protocolSdk, 'getTotalBonded').returns(totalBondedStake) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + + const totalBondedStub = sinon + .stub(protocolService, 'getTotalBonded') + .returns(totalBondedStake) + const rewardExpected = '36.6' // when @@ -97,13 +100,13 @@ describe('## DelegateService test', () => { // then expect(getSummaryStub.called) - expect(getMintedTokensForNextRoundStub.called) - expect(getTotalBondedStub.called) + expect(mintedTokensStub.called) + expect(totalBondedStub.called) expect(result).equal(rewardExpected) // restore stubs getSummaryStub.restore() - getMintedTokensForNextRoundStub.restore() - getTotalBondedStub.restore() + mintedTokensStub.restore() + totalBondedStub.restore() }) it('0 minted tokens for next round, protocol bondedStake is 1400, the bondedStake of the delegate is 512.4 (36.6% of the totalBonded), result should be 0', async () => { // given @@ -111,11 +114,11 @@ describe('## DelegateService test', () => { delegate.totalStake = unitAmountInTokenUnits('512.4') const totalBondedStake = unitAmountInTokenUnits(1400) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const getMintedTokensForNextRoundStub = sinon - .stub(protocolSdk, 'getMintedTokensForNextRound') - .returns(0) - const getTotalBondedStub = sinon.stub(protocolSdk, 'getTotalBonded').returns(totalBondedStake) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + const mintedTokensStub = sinon.stub(protocolService, 'getMintedTokensForNextRound').returns(0) + + const totalBondedStub = sinon + .stub(protocolService, 'getTotalBonded') + .returns(totalBondedStake) const rewardExpected = '0' // when @@ -123,13 +126,13 @@ describe('## DelegateService test', () => { // then expect(getSummaryStub.called) - expect(getMintedTokensForNextRoundStub.called) - expect(getTotalBondedStub.called) + expect(mintedTokensStub.called) + expect(totalBondedStub.called) expect(result).equal(rewardExpected) // restore stubs getSummaryStub.restore() - getMintedTokensForNextRoundStub.restore() - getTotalBondedStub.restore() + mintedTokensStub.restore() + totalBondedStub.restore() }) it('1000 minted tokens for next round, protocol bondedStake is 10000, the bondedStake of the delegate is 100 (1% of the totalBonded), result should be 10', async () => { // given @@ -137,11 +140,13 @@ describe('## DelegateService test', () => { delegate.totalStake = unitAmountInTokenUnits('100') const totalBondedStake = unitAmountInTokenUnits(10000) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const getMintedTokensForNextRoundStub = sinon - .stub(protocolSdk, 'getMintedTokensForNextRound') + const mintedTokensStub = sinon + .stub(protocolService, 'getMintedTokensForNextRound') .returns(1000) - const getTotalBondedStub = sinon.stub(protocolSdk, 'getTotalBonded').returns(totalBondedStake) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) + + const totalBondedStub = sinon + .stub(protocolService, 'getTotalBonded') + .returns(totalBondedStake) const rewardExpected = '10' // when @@ -149,13 +154,13 @@ describe('## DelegateService test', () => { // then expect(getSummaryStub.called) - expect(getMintedTokensForNextRoundStub.called) - expect(getTotalBondedStub.called) + expect(mintedTokensStub.called) + expect(totalBondedStub.called) expect(result).equal(rewardExpected) // restore stubs getSummaryStub.restore() - getMintedTokensForNextRoundStub.restore() - getTotalBondedStub.restore() + mintedTokensStub.restore() + totalBondedStub.restore() }) }) describe('# getDelegateNextReward', () => { @@ -164,7 +169,6 @@ describe('## DelegateService test', () => { const delegate = createTranscoder() delegate.pendingRewardCut = MathBN.mul(10, 10000) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) const getDelegateProtocolNextRewardStub = sinon .stub(delegateService, 'getDelegateProtocolNextReward') .returns(1000) @@ -186,7 +190,6 @@ describe('## DelegateService test', () => { const delegate = createTranscoder() delegate.pendingRewardCut = MathBN.mul(10, 10000) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) const getDelegateProtocolNextRewardStub = sinon .stub(delegateService, 'getDelegateProtocolNextReward') .returns(198761) @@ -208,7 +211,6 @@ describe('## DelegateService test', () => { const delegate = createTranscoder() delegate.pendingRewardCut = MathBN.mul(10, 10000) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) const getDelegateProtocolNextRewardStub = sinon .stub(delegateService, 'getDelegateProtocolNextReward') .returns(0) @@ -232,7 +234,6 @@ describe('## DelegateService test', () => { const delegate = createTranscoder() delegate.pendingRewardCut = MathBN.mul(10, 10000) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) const getDelegateProtocolNextRewardStub = sinon .stub(delegateService, 'getDelegateProtocolNextReward') .returns(1000) @@ -254,7 +255,6 @@ describe('## DelegateService test', () => { const delegate = createTranscoder() delegate.pendingRewardCut = MathBN.mul(10, 10000) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) const getDelegateProtocolNextRewardStub = sinon .stub(delegateService, 'getDelegateProtocolNextReward') .returns(19843.21064318) @@ -276,7 +276,6 @@ describe('## DelegateService test', () => { const delegate = createTranscoder() delegate.pendingRewardCut = MathBN.mul(10, 10000) const getSummaryStub = sinon.stub(delegatesGraphql, 'getDelegateSummary').returns(delegate) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) const getDelegateProtocolNextRewardStub = sinon .stub(delegateService, 'getDelegateProtocolNextReward') .returns(0) @@ -294,132 +293,6 @@ describe('## DelegateService test', () => { getDelegateProtocolNextRewardStub.restore() }) }) - describe('# getDelegatorNextReturn', () => { - // Delegate bondedStake = 1000 - // DelegatorBonded stake = 100 (10% participation) - // Delegate nextRewardToDelegators = 500 - // Result = 50 - it('the next reward to delegators is 500, the % of participation of the delegator is 10%, result should be 50', async () => { - // given - const delegator = createDelegator() - delegator.totalStake = unitAmountInTokenUnits(100) - const delegateTotalStake = unitAmountInTokenUnits(1000) - const getLivepeerDelegatorAccountSub = sinon - .stub(protocolSdk, 'getLivepeerDelegatorAccount') - .returns(delegator) - const getDelegateTotalStakeStub = sinon - .stub(delegatesGraphql, 'getDelegateTotalStake') - .returns(delegateTotalStake) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) - const getDelegateRewardToDelegatorsSub = sinon - .stub(delegateService, 'getDelegateRewardToDelegators') - .returns(500) - const rewardExpected = '50' - - // when - const result = await delegateService.getDelegatorNextReturn() - - // then - expect(getLivepeerDelegatorAccountSub.called) - expect(getDelegateTotalStakeStub.called) - expect(getDelegateRewardToDelegatorsSub.called) - expect(result).equal(rewardExpected) - // restore stubs - getLivepeerDelegatorAccountSub.restore() - getDelegateTotalStakeStub.restore() - getDelegateRewardToDelegatorsSub.restore() - }) - it('the next reward to delegators is 4866341500, the % of participation of the delegator is 10%, result should be 486634150', async () => { - // given - const delegator = createDelegator() - delegator.totalStake = unitAmountInTokenUnits(100) - const delegateTotalStake = unitAmountInTokenUnits(1000) - const getLivepeerDelegatorAccountSub = sinon - .stub(protocolSdk, 'getLivepeerDelegatorAccount') - .returns(delegator) - const getDelegateTotalStakeStub = sinon - .stub(delegatesGraphql, 'getDelegateTotalStake') - .returns(delegateTotalStake) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) - const getDelegateRewardToDelegatorsSub = sinon - .stub(delegateService, 'getDelegateRewardToDelegators') - .returns(4866341500) - const rewardExpected = '486634150' - - // when - const result = await delegateService.getDelegatorNextReturn() - - // then - expect(getLivepeerDelegatorAccountSub.called) - expect(getDelegateTotalStakeStub.called) - expect(getDelegateRewardToDelegatorsSub.called) - expect(result).equal(rewardExpected) - // restore stubs - getLivepeerDelegatorAccountSub.restore() - getDelegateTotalStakeStub.restore() - getDelegateRewardToDelegatorsSub.restore() - }) - it('the next reward to delegators is 4866341500, the % of participation of the delegator is 99%, result should be 4817678085', async () => { - // given - const delegator = createDelegator() - delegator.totalStake = unitAmountInTokenUnits(990) - const delegateTotalStake = unitAmountInTokenUnits(1000) - const getLivepeerDelegatorAccountSub = sinon - .stub(protocolSdk, 'getLivepeerDelegatorAccount') - .returns(delegator) - const getDelegateTotalStakeStub = sinon - .stub(delegatesGraphql, 'getDelegateTotalStake') - .returns(delegateTotalStake) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) - const getDelegateRewardToDelegatorsSub = sinon - .stub(delegateService, 'getDelegateRewardToDelegators') - .returns(4866341500) - const rewardExpected = '4817678085' - - // when - const result = await delegateService.getDelegatorNextReturn() - - // then - expect(getLivepeerDelegatorAccountSub.called) - expect(getDelegateTotalStakeStub.called) - expect(getDelegateRewardToDelegatorsSub.called) - expect(result).equal(rewardExpected) - // restore stubs - getLivepeerDelegatorAccountSub.restore() - getDelegateTotalStakeStub.restore() - getDelegateRewardToDelegatorsSub.restore() - }) - it('the next reward to delegators is 0, the % of participation of the delegator is 99%, result should be 0', async () => { - // given - const delegator = createDelegator() - delegator.totalStake = unitAmountInTokenUnits(990) - const delegateTotalStake = unitAmountInTokenUnits(1000) - const getLivepeerDelegatorAccountSub = sinon - .stub(protocolSdk, 'getLivepeerDelegatorAccount') - .returns(delegator) - const getDelegateTotalStakeStub = sinon - .stub(delegatesGraphql, 'getDelegateTotalStake') - .returns(delegateTotalStake) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) - const getDelegateRewardToDelegatorsSub = sinon - .stub(delegateService, 'getDelegateRewardToDelegators') - .returns(0) - const rewardExpected = '0' - - // when - const result = await delegateService.getDelegatorNextReturn() - - // then - expect(getLivepeerDelegatorAccountSub.called) - expect(getDelegateTotalStakeStub.called) - expect(getDelegateRewardToDelegatorsSub.called) - expect(result).equal(rewardExpected) - // restore stubs - getLivepeerDelegatorAccountSub.restore() - getDelegateTotalStakeStub.restore() - getDelegateRewardToDelegatorsSub.restore() - }) - }) describe('# getMissedRewardCalls', () => { describe('# Missed reward call calculation', () => { it('There are 30 rounds, 10 of them do not have reward object, result should be 10', async () => { @@ -437,12 +310,11 @@ describe('## DelegateService test', () => { rewards.push(newReward) } const getDelegateRewardsStub = sinon - .stub(delegatesGraphql, 'getDelegateRewards') + .stub(delegateService, 'getDelegateRewards') .returns(rewards) const getCurrentRoundStub = sinon - .stub(delegatesGraphql, 'getCurrentRound') + .stub(protocolService, 'getCurrentRound') .returns(currentRound) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) // when const missedRewardCalls = await delegateService.getMissedRewardCalls(rewards, currentRound) @@ -472,12 +344,11 @@ describe('## DelegateService test', () => { rewards.push(newReward) } const getDelegateRewardsStub = sinon - .stub(delegatesGraphql, 'getDelegateRewards') + .stub(delegateService, 'getDelegateRewards') .returns(rewards) const getCurrentRoundStub = sinon - .stub(delegatesGraphql, 'getCurrentRound') + .stub(protocolService, 'getCurrentRound') .returns(currentRound) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) // when const missedRewardCalls = await delegateService.getMissedRewardCalls(rewards, currentRound) @@ -503,12 +374,11 @@ describe('## DelegateService test', () => { } const getDelegateRewardsStub = sinon - .stub(delegatesGraphql, 'getDelegateRewards') + .stub(delegateService, 'getDelegateRewards') .returns(rewards) const getCurrentRoundStub = sinon - .stub(delegatesGraphql, 'getCurrentRound') + .stub(protocolService, 'getCurrentRound') .returns(currentRound) - const delegateService = getDelegateService(delegatesGraphql, protocolSdk) // when const missedRewardCalls = await delegateService.getMissedRewardCalls(rewards, currentRound) From 9cd1200ed89615996e82fba052f075921e4f884c Mon Sep 17 00:00:00 2001 From: Mariano Aguero Date: Wed, 26 Jun 2019 16:18:24 -0300 Subject: [PATCH 20/20] Fix lint errors and typos --- package.json | 2 +- server/helpers/sdk/delegator.js | 1 + server/helpers/services/delegateService.js | 3 ++- server/helpers/services/delegatorService.js | 3 ++- server/subscriber/subscriber.controller.js | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 64a50c6..898c3a8 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "yarn": ">=1.5.1" }, "scripts": { - "start": "nodemon --harmony index.js ", + "start": "nodemon --harmony index.js", "lint": "esw *.js server config --color", "lint:watch": "npm run lint -- --watch", "test": "NODE_ENV=test ./node_modules/.bin/mocha test/*.test.js --timeout=1200000 --ui bdd --reporter spec --colors server --harmony --exit", diff --git a/server/helpers/sdk/delegator.js b/server/helpers/sdk/delegator.js index 8b20c70..190681e 100644 --- a/server/helpers/sdk/delegator.js +++ b/server/helpers/sdk/delegator.js @@ -1,5 +1,6 @@ const LivepeerSDK = require('@mariano-aguero/sdk') const { MathBN } = require('../utils') + const getLivepeerDelegatorAccount = async address => { if (!address) { return null diff --git a/server/helpers/services/delegateService.js b/server/helpers/services/delegateService.js index 4bb0efc..dbfb8d1 100644 --- a/server/helpers/services/delegateService.js +++ b/server/helpers/services/delegateService.js @@ -10,7 +10,8 @@ const { calculateMissedRewardCalls } = require('../utils') const promiseRetry = require('promise-retry') let delegateServiceInstance -const delegatesSource = require('../graphql/queries') // the default source for delegates is GRAPHQL +// the default source for delegates is GRAPHQL +const delegatesSource = require('../graphql/queries') const getDelegateService = (source = delegatesSource) => { if (!delegateServiceInstance) { diff --git a/server/helpers/services/delegatorService.js b/server/helpers/services/delegatorService.js index a36f942..6783c1d 100644 --- a/server/helpers/services/delegatorService.js +++ b/server/helpers/services/delegatorService.js @@ -1,6 +1,7 @@ const _ = require('lodash') let delegatorServiceInstance -const defaultSource = require('../sdk/delegator') // the delegate information comes from the SDK as default, graphql is not implemented +// The delegate information comes from the SDK as default, graphql is not implemented +const defaultSource = require('../sdk/delegator') const getDelegatorService = (source = defaultSource) => { if (!delegatorServiceInstance) { diff --git a/server/subscriber/subscriber.controller.js b/server/subscriber/subscriber.controller.js index f13fb9a..43fa2af 100644 --- a/server/subscriber/subscriber.controller.js +++ b/server/subscriber/subscriber.controller.js @@ -283,7 +283,7 @@ const summary = async (req, res, next) => { res.json(data) } catch (error) { - console.error('eee ', error) + console.error(error) next(error) } }