From e9bfc105880e90dd09935690ea789ed10af911c8 Mon Sep 17 00:00:00 2001 From: Pavel Khavilov <43392281+Pasha8914@users.noreply.github.com> Date: Mon, 11 Jul 2022 16:57:38 +1000 Subject: [PATCH] Refactor and features (#17) * feat: features and refactor * fixed return types * update README Co-authored-by: Danil Kovtonyuk --- .eslintrc | 38 + .eslintrc.js | 17 - .github/workflows/nodejs.yml | 3 +- .gitignore | 93 +- .nvmrc | 1 + .prettierignore | 1 + .prettierrc | 8 +- README.md | 268 ++- package.json | 29 +- src/config/arbitrum.ts | 10 + src/config/avax.ts | 23 + src/config/bsc.ts | 16 +- src/config/index.ts | 80 +- src/config/mainnet.ts | 38 +- src/config/optimism.ts | 18 + src/config/polygon.ts | 10 +- src/config/xdai.ts | 10 +- src/constants/index.ts | 14 + src/index.ts | 279 +-- src/services/gas-estimation/constants.ts | 26 + src/services/gas-estimation/eip1559.ts | 137 ++ src/services/gas-estimation/index.ts | 2 + src/services/gas-estimation/types.ts | 37 + .../gas-price-oracle/gas-price-oracle.ts | 96 ++ src/services/gas-price-oracle/index.ts | 2 + src/services/gas-price-oracle/types.ts | 54 + src/services/index.ts | 6 + src/services/legacy-gas-price/constants.ts | 10 + src/services/legacy-gas-price/index.ts | 2 + src/services/legacy-gas-price/legacy.ts | 292 ++++ src/services/legacy-gas-price/types.ts | 78 + src/services/rpcFetcher/fetcher.ts | 23 + src/services/rpcFetcher/index.ts | 2 + src/services/rpcFetcher/types.ts | 7 + src/tests/complex.test.ts | 134 ++ src/tests/eip1559.test.ts | 134 ++ src/tests/legacy.test.ts | 358 ++++ src/types.ts | 80 +- src/utils/crypto.ts | 20 + src/utils/index.ts | 2 + src/utils/math.ts | 45 + tests/index.test.ts | 333 ---- tsconfig.esm.json | 9 + tsconfig.json | 92 +- yarn.lock | 1517 ++++++++++++----- 45 files changed, 3137 insertions(+), 1317 deletions(-) create mode 100644 .eslintrc delete mode 100644 .eslintrc.js create mode 100644 .nvmrc create mode 100644 .prettierignore create mode 100644 src/config/arbitrum.ts create mode 100644 src/config/avax.ts create mode 100644 src/config/optimism.ts create mode 100644 src/constants/index.ts create mode 100644 src/services/gas-estimation/constants.ts create mode 100644 src/services/gas-estimation/eip1559.ts create mode 100644 src/services/gas-estimation/index.ts create mode 100644 src/services/gas-estimation/types.ts create mode 100644 src/services/gas-price-oracle/gas-price-oracle.ts create mode 100644 src/services/gas-price-oracle/index.ts create mode 100644 src/services/gas-price-oracle/types.ts create mode 100644 src/services/index.ts create mode 100644 src/services/legacy-gas-price/constants.ts create mode 100644 src/services/legacy-gas-price/index.ts create mode 100644 src/services/legacy-gas-price/legacy.ts create mode 100644 src/services/legacy-gas-price/types.ts create mode 100644 src/services/rpcFetcher/fetcher.ts create mode 100644 src/services/rpcFetcher/index.ts create mode 100644 src/services/rpcFetcher/types.ts create mode 100644 src/tests/complex.test.ts create mode 100644 src/tests/eip1559.test.ts create mode 100644 src/tests/legacy.test.ts create mode 100644 src/utils/crypto.ts create mode 100644 src/utils/index.ts create mode 100644 src/utils/math.ts delete mode 100644 tests/index.test.ts create mode 100644 tsconfig.esm.json diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..cc050a9 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,38 @@ +{ + "env": { + "node": true, + "browser": true, + "es6": true, + "mocha": true + }, + "plugins": ["prettier", "eslint-plugin-import", "eslint-plugin-node", "eslint-plugin-promise", "@typescript-eslint"], + "extends": ["prettier", "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "parser": "@typescript-eslint/parser", + "project": "./tsconfig.json", + "sourceType": "module", + "target": "esnext", + "module": "commonjs" + }, + "rules": { + "node/no-callback-literal": 0, + "prettier/prettier": ["error", { "printWidth": 130 }], + "jsx-quotes": ["error", "prefer-single"], + "@typescript-eslint/restrict-template-expressions": ["warn", { "allowNumber": true }], + "@typescript-eslint/explicit-function-return-type": 0, + "@typescript-eslint/array-type": 2, + "@typescript-eslint/camelcase": 0, + "@typescript-eslint/consistent-type-definitions": 0, + "@typescript-eslint/no-empty-function": 2, + "@typescript-eslint/no-empty-interface": 2, + "@typescript-eslint/no-explicit-any": 2, + "@typescript-eslint/no-extra-non-null-assertion": 2, + "@typescript-eslint/require-await": 2, + "@typescript-eslint/no-floating-promises": 0, + "@typescript-eslint/strict-boolean-expressions": 0 + } +} diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 0bb312c..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', // Specifies the ESLint parser - parserOptions: { - ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features - sourceType: 'module', // Allows for the use of imports - }, - extends: [ - 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin - 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier - 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. - ], - rules: { - indent: ['error', 2], - // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs - // e.g. "@typescript-eslint/explicit-function-return-type": "off", - }, -}; diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 90f4ff1..ae93687 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: - node-version: 12 + node-version: 16.15.1 - run: yarn install --frozen-lockfile - run: yarn test - run: yarn lint @@ -27,7 +27,6 @@ jobs: - name: Checkout uses: actions/checkout@v2 - run: yarn install - - run: yarn run build - name: NPM login # NPM doesn't understand env vars and needs auth file lol run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc diff --git a/.gitignore b/.gitignore index 9b26ed0..0602661 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,91 @@ -node_modules -lib \ No newline at end of file +# Created by .ignore support plugin (hsz.mobi) +### Node template +# Logs +/logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# Nuxt generate +dist + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless + +# IDE / Editor +.idea + +# Service worker +sw.* + +# macOS +.DS_Store + +# Vim swap files +*.swp diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..d928989 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +16.15.1 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a65b417 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +lib diff --git a/.prettierrc b/.prettierrc index 66a42ff..9f77592 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,8 @@ { - "semi": true, + "semi": false, "trailingComma": "all", "singleQuote": true, - "printWidth": 110, - "tabWidth": 2, - "arrowParens": "avoid" + "jsxSingleQuote": true, + "printWidth": 130, + "tabWidth": 2 } diff --git a/README.md b/README.md index bf86878..7753306 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Gas Price Oracle library for Ethereum dApps [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/peppersec/gas-price-oracle/Node.js%20CI)](https://github.com/peppersec/gas-price-oracle/actions) [![npm](https://img.shields.io/npm/v/gas-price-oracle)](https://www.npmjs.com/package/gas-price-oracle) -A library that has a collection of onchain and offchain gas price oracle URLs +This is a library with a collection of onchain and offchain gas price oracle URLs ## Supported networks @@ -10,7 +10,6 @@ Current offchain list: - https://ethgasstation.info/json/ethgasAPI.json - https://etherchain.org/api/gasnow -- https://blockscout.com/eth/mainnet/api/v1/gas-price-oracle Current onchain list: @@ -22,7 +21,7 @@ Current offchain list: - https://ztake.org/ -### xDAI Chain +### Gnosis Chain Current offchain list: @@ -34,77 +33,266 @@ Current offchain list: - https://gasstation-mainnet.matic.network/ +### Avalanche C Network + +Current offchain list: + +- https://gavax.blockscan.com/gasapi.ashx?apikey=key&method=gasoracle + ## Installation `npm i gas-price-oracle` +or +`yarn add gas-price-oracle` ## Import ```js -const { GasPriceOracle } = require('gas-price-oracle'); +const { GasPriceOracle } = require('gas-price-oracle') +or +import { GasPriceOracle } from 'gas-price-oracle' ``` ## Usage -### Basic +### Configuration -```js -const options = { +```typescript +type GasPrice = Record<'instant' | 'fast' | 'standard' | 'low', number> + +type EstimatedGasPrice = { + maxFeePerGas: number + baseFee: number | undefined + maxPriorityFeePerGas: number +} + +type FallbackGasPrices = { + gasPrices?: GasPrice + estimated?: EstimatedGasPrice +} + +type GasOracleOptions = { + chainId?: number + timeout?: number + defaultRpc?: string + blocksCount?: number + percentile?: number + fallbackGasPrices?: FallbackGasPrices +} + +const options: GasOracleOptions = { chainId: 1, + percentile: 5, // Which percentile of effective priority fees to include + blocksCount: 10, // How many blocks to consider for priority fee estimation defaultRpc: 'https://api.mycryptoapi.com/eth', - timeout: 10000, - defaultFallbackGasPrices: { + timeout: 10000, // specifies the number of milliseconds before the request times out. + fallbackGasPrices: { + gasPrices: { + instant: 28, + fast: 22, + standard: 17, + low: 11, + }, + estimated: { + maxFeePerGas: 20, + maxPriorityFeePerGas: 3, + }, + }, +} +``` + +### EIP-1559 (estimated) gasPrice only + +```typescript +const oracle = new GasPriceOracle({ chainId: 1 }) + +type EstimatedGasPrice = { + maxFeePerGas: number + baseFee: number | undefined + maxPriorityFeePerGas: number +} + +fallbackGasPrices: EstimatedGasPrice = { + maxFeePerGas: 20, + maxPriorityFeePerGas: 3, +} + +oracle.eip1559.estimateFees(fallbackGasPrices).then((gasPrices: EstimatedGasPrice) => { + console.log(gasPrices) // { baseFee: 14, maxFeePerGas: 17, maxPriorityFeePerGas: 3 } +}) +``` + +### Legacy gasPrice only + +```typescript +const oracle = new GasPriceOracle({ chainId: 1 }) + +type GasPrice = Record<'instant' | 'fast' | 'standard' | 'low', number> + +fallbackGasPrices: GasPrice = { + instant: 28, + fast: 22, + standard: 17, + low: 11, +} + +oracle.legacy.gasPrices(fallbackGasPrices).then((gasPrices: GasPrice) => { + console.log(gasPrices) // { instant: 21.5, fast: 19, standard: 17, low: 15 } +}) +``` + +The `oracle.legacy.gasPrices` method also accepts `shouldGetMedian` argument (`true`) by default. For more details see [below](#offchain-oracles-only-get-median-price). +Under the hood it's a combination of `fetchMedianGasPriceOffChain`(`fetchGasPricesOffChain`) and `fetchGasPricesOnChain` methods. + +### Estimated gasPrices (EIP-1559) and Legacy gasPrice + +```ts +const oracle = new GasPriceOracle(options) + +type GasPriceWithEstimate = { + gasPrices: GasPrice + estimate: EstimatedGasPrice +} + +type GasPricesWithEstimateInput = { + shouldGetMedian?: boolean + fallbackGasPrices?: FallbackGasPrices +} + +// optional fallbackGasPrices +const fallbackGasPrices: FallbackGasPrices = { + gasPrices: { instant: 28, fast: 22, standard: 17, low: 11, }, -}; -const oracle = new GasPriceOracle(options); -// optional fallbackGasPrices -const fallbackGasPrices = { - instant: 70, - fast: 31, - standard: 20, - low: 7, -}; -oracle.gasPrices(fallbackGasPrices).then(gasPrices => { - console.log(gasPrices); // { instant: 50, fast: 21, standard: 10, low: 3 } -}); + estimated: { + maxFeePerGas: 20, + maxPriorityFeePerGas: 3, + }, +} + +oracle.gasPricesWithEstimate({ fallbackGasPrices, shouldGetMedian: true }).then((gasPrices: GasPriceWithEstimate) => { + console.log(gasPrices) // { + // estimated: { baseFee: 14, maxFeePerGas: 17, maxPriorityFeePerGas: 3 }, + // gasPrices: { instant: 21.5, fast: 19, standard: 17, low: 15 } + // }} +}) ``` -The `gasPrices` method also accepts `median` argument (`true`) by default. For more details see [below](#offchain-oracles-only-get-median-price). -Under the hood it's a combination of `fetchMedianGasPriceOffChain`(`fetchGasPricesOffChain`) and `fetchGasPricesOnChain` methods. +### Estimated gasPrices (EIP-1559) or Legacy gasPrice + +```typescript +const oracle = new GasPriceOracle(options) + +type GetGasPriceInput = { + isLegacy?: boolean + shouldGetMedian?: boolean + fallbackGasPrices?: GasPrice +} + +// optional fallbackGasPrices +const fallbackGasPrices: FallbackGasPrices = { + gasPrices: { + instant: 28, + fast: 22, + standard: 17, + low: 11, + }, + estimated: { + maxFeePerGas: 20, + maxPriorityFeePerGas: 3, + }, +} + +oracle.gasPrices({ fallbackGasPrices, shouldGetMedian: true }).then((gasPrices: GasPrice | EstimatedGasPrice) => { + console.log(gasPrices) // { + // baseFee: 14, maxFeePerGas: 17, maxPriorityFeePerGas: 3 || + // instant: 21.5, fast: 19, standard: 17, low: 15 + // }} +}) +``` + +The `gasPrices` method also accepts `isLegacy` argument (`false`) by default. If `isLegacy: true` - `legacy gasPrice` will be provided. If the `estimate Gas` crashes, `legacy gas Price` will be provided. + +### Get transaction gasPrice params + +```typescript +const oracle = new GasPriceOracle(options) + +type GetTxGasParamsInput = { + bumpPercent?: number + legacySpeed?: GasPriceKey + isLegacy?: boolean + shouldGetMedian?: boolean + fallbackGasPrices?: FallbackGasPrices +} + +type GetTxGasParamsRes = + | { + gasPrice: number + } + | { + maxFeePerGas: number + maxPriorityFeePerGas: number + } + +const gasParams: GetTxGasParamsRes = await oracle.getTxGasParams({ legacySpeed: 'fast', bumpPercent: 30 }) +console.log(gasParams) // { maxFeePerGas: 17, maxPriorityFeePerGas: 3 } || { gasPrice: 19 } + +web3.eth.sendTransaction({ + from: '0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8', + to: '0xac03bb73b6a9e108530aff4df5077c2b3d481e5a', + nonce: '0', + gasLimit: '21000', + value: '10000000000', + ...gasParams, +}) +``` + +`bumpPercent` argument (`0` by default) - response data will increase by `bumpPercent`%. +`legacySpeed` argument (`fast` by default) - select the speed of legacy gasPrice. ### Offchain oracles only -```js -const oracle = new GasPriceOracle(); +```typescript +const oracle = new GasPriceOracle({ chainId: 1 }) -oracle.fetchGasPricesOffChain().then(gasPrices => { - console.log(gasPrices); // { instant: 50, fast: 21, standard: 10, low: 3 } -}); +// shouldGetMedian: boolean | undefined +oracle.legacy.fetchGasPricesOffChain((shouldGetMedian = true)).then((gasPrices: GasPrice) => { + console.log(gasPrices) // { instant: 50, fast: 21, standard: 10, low: 3 } +}) ``` ### Offchain oracles only (get median price) -```js -const oracle = new GasPriceOracle(); +```typescript +const oracle = new GasPriceOracle({ chainId: 1 }) -oracle.fetchMedianGasPriceOffChain().then(gasPrices => { - console.log(gasPrices); // { instant: 50, fast: 21, standard: 10, low: 3 } -}); +oracle.legacy.fetchMedianGasPriceOffChain().then((gasPrices: GasPrice) => { + console.log(gasPrices) // { instant: 50, fast: 21, standard: 10, low: 3 } +}) ``` -it returns the median gas price of all the oracles configured. +This command provides the median gas price of all configured oracles. ### Custom RPC URL for onchain oracles -```js -const defaultRpc = 'https://mainnet.infura.io/v3/'; -const oracle = new GasPriceOracle({ defaultRpc }); +```typescript +const defaultRpc = 'https://mainnet.infura.io/v3/' +const oracle = new GasPriceOracle({ defaultRpc, chainId: 1 }) -oracle.fetchGasPricesOnChain().then(gasPrices => { - console.log(gasPrices); // 21 -}); +oracle.legacy.fetchGasPricesOnChain().then((gasPrices: number) => { + console.log(gasPrices) // 21 +}) +``` + +To get gasPrices from a chain outside of the application's chain list (Binance, Gnosis, Polygon, Avalanche), you should enter the rpcUrl into initial GasPriceOracle options\_ + +```typescript +const defaultRpc = 'https://rpc.goerli.mudit.blog/' // goerli public rpcUrl +const oracle = new GasPriceOracle({ defaultRpc, chainId: 5 }) + +oracle.gasPrices() ``` diff --git a/package.json b/package.json index 47c4a7e..28ce3ee 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,34 @@ { "name": "gas-price-oracle", - "version": "0.4.7", + "version": "0.5.0", "description": "Gas Price Oracle library for Ethereum dApps.", - "main": "lib/index.js", "homepage": "https://github.com/peppersec/gas-price-oracle", + "main": "./lib/index.js", + "module": "./lib/esm/index.js", + "types": "./lib/index.d.ts", "repository": { "type": "git", "url": "https://github.com/peppersec/gas-price-oracle.git" }, - "types": "lib/index.d.ts", - "prepare": "npm run build", - "prepublishOnly": "npm test && npm run lint", "scripts": { - "test": "mocha -r ts-node/register --timeout 30000 --exit src tests/*.test.ts", - "build": "tsc", + "test": "ts-mocha --timeout 30000 --paths 'src/tests/*.test.ts'", + "build": "tsc && tsc-alias", + "build:esm": "tsc -p tsconfig.esm.json && tsc-alias -p tsconfig.esm.json", "eslint": "eslint 'src/*.ts'", "prettier:check": "prettier --check . --config .prettierrc", "prettier:fix": "prettier --write . --config .prettierrc", - "lint": "yarn eslint && yarn prettier:check" + "lint": "yarn eslint && yarn prettier:check", + "prepare": "yarn build && yarn build:esm", + "prepublishOnly": "yarn test && yarn lint" }, "author": "Alexey Pertsev (https://peppersec.com)", "keywords": [ "Gas", "Gas price", "Ethereum", - "Oracle" + "Oracle", + "EIP-1559", + "London Fork" ], "license": "MIT", "devDependencies": { @@ -39,12 +43,17 @@ "chai-as-promised": "^7.1.1", "eslint": "^7.11.0", "eslint-config-prettier": "^6.13.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.4", + "eslint-plugin-promise": "^6.0.0", "mocha": "^7.2.0", "mockery": "^2.1.0", "prettier": "^2.1.2", + "ts-mocha": "^10.0.0", "ts-node": "^8.10.1", - "typescript": "^4.0.3" + "tsc-alias": "^1.6.11", + "typescript": "^4.7.4" }, "dependencies": { "axios": "^0.21.2", diff --git a/src/config/arbitrum.ts b/src/config/arbitrum.ts new file mode 100644 index 0000000..bc0c17c --- /dev/null +++ b/src/config/arbitrum.ts @@ -0,0 +1,10 @@ +import { OffChainOracles, OnChainOracles } from '@/services' + +export const offChainOracles: OffChainOracles = {} + +export const onChainOracles: OnChainOracles = {} + +export default { + offChainOracles, + onChainOracles, +} diff --git a/src/config/avax.ts b/src/config/avax.ts new file mode 100644 index 0000000..1fe61cd --- /dev/null +++ b/src/config/avax.ts @@ -0,0 +1,23 @@ +import { OffChainOracle, OffChainOracles, OnChainOracles } from '@/services' + +const avalancheGasStation: OffChainOracle = { + name: 'avalancheGasStation', + url: 'https://gavax.blockscan.com/gasapi.ashx?apikey=key&method=gasoracle', + instantPropertyName: 'FastGasPrice', + fastPropertyName: 'FastGasPrice', + standardPropertyName: 'ProposeGasPrice', + lowPropertyName: 'SafeGasPrice', + denominator: 1, + additionalDataProperty: 'result', +} + +export const offChainOracles: OffChainOracles = { + avalancheGasStation, +} + +export const onChainOracles: OnChainOracles = {} + +export default { + offChainOracles, + onChainOracles, +} diff --git a/src/config/bsc.ts b/src/config/bsc.ts index e745d0e..cec3707 100644 --- a/src/config/bsc.ts +++ b/src/config/bsc.ts @@ -1,23 +1,23 @@ -import { OffChainOracle, OffChainOracles, OnChainOracles } from '../types'; +import { OffChainOracle, OffChainOracles, OnChainOracles } from '@/services' const ztake: OffChainOracle = { name: 'ztake', url: 'https://blockchains.ztake.org/api/h6WnmwNqw9CAJHzej5W4gD6LZ9n7v8EK/gasprice/bsc/', - instantPropertyName: 'percentile_90', - fastPropertyName: 'percentile_80', - standardPropertyName: 'percentile_60', + instantPropertyName: 'percentile_60', + fastPropertyName: 'percentile_50', + standardPropertyName: 'percentile_40', lowPropertyName: 'percentile_30', denominator: 1, additionalDataProperty: null, -}; +} export const offChainOracles: OffChainOracles = { ztake, -}; +} -export const onChainOracles: OnChainOracles = {}; +export const onChainOracles: OnChainOracles = {} export default { offChainOracles, onChainOracles, -}; +} diff --git a/src/config/index.ts b/src/config/index.ts index d15bedb..dafe00c 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,20 +1,78 @@ -import { NetworkConfig } from '../types'; +import bscOracles from './bsc' +import xdaiOracles from './xdai' +import avalancheOracles from './avax' +import mainnetOracles from './mainnet' +import polygonOracles from './polygon' +import optimismOracles from './optimism' +import arbitrumOracles from './arbitrum' -import mainnetOracles from './mainnet'; -import bscOracles from './bsc'; -import xdaiOracles from './xdai'; -import polygonOracles from './polygon'; +import { NetworksConfig } from '@/types' export enum ChainId { MAINNET = 1, BSC = 56, XDAI = 100, POLYGON = 137, + OPTIMISM = 10, + ARBITRUM = 42161, + AVAX = 43114, } -export const NETWORKS: NetworkConfig = { - [ChainId.MAINNET]: mainnetOracles, - [ChainId.BSC]: bscOracles, - [ChainId.XDAI]: xdaiOracles, - [ChainId.POLYGON]: polygonOracles, -}; +export const NETWORKS: Record = { + [ChainId.MAINNET]: { + oracles: mainnetOracles, + rpcUrl: 'https://api.mycryptoapi.com/eth', + defaultGasPrice: 22, + maxGasPrice: 1500, + blocksCount: 10, + percentile: 5, + }, + [ChainId.BSC]: { + oracles: bscOracles, + rpcUrl: 'https://bsc-dataseed1.ninicoin.io', + defaultGasPrice: 5, + maxGasPrice: 200, + blocksCount: 10, + percentile: 5, + }, + [ChainId.XDAI]: { + oracles: xdaiOracles, + rpcUrl: 'https://rpc.gnosischain.com', + defaultGasPrice: 5, + maxGasPrice: 200, + blocksCount: 200, + percentile: 5, + }, + [ChainId.POLYGON]: { + oracles: polygonOracles, + rpcUrl: 'https://rpc-mainnet.maticvigil.com', + defaultGasPrice: 75, + maxGasPrice: 1000, + blocksCount: 10, + percentile: 5, + }, + [ChainId.OPTIMISM]: { + oracles: optimismOracles, + rpcUrl: 'https://mainnet.optimism.io', + defaultGasPrice: 0.001, + maxGasPrice: 5, + blocksCount: 10, + percentile: 5, + }, + [ChainId.ARBITRUM]: { + oracles: arbitrumOracles, + rpcUrl: 'https://arb1.arbitrum.io/rpc', + defaultGasPrice: 3, + maxGasPrice: 15, + blocksCount: 10, + percentile: 5, + }, + [ChainId.AVAX]: { + oracles: avalancheOracles, + rpcUrl: 'https://api.avax.network/ext/bc/C/rpc', + defaultGasPrice: 50, + maxGasPrice: 1000, + blocksCount: 10, + percentile: 5, + }, +} diff --git a/src/config/mainnet.ts b/src/config/mainnet.ts index 2eb350f..add5f9d 100644 --- a/src/config/mainnet.ts +++ b/src/config/mainnet.ts @@ -1,4 +1,4 @@ -import { OffChainOracle, OnChainOracle, OffChainOracles, OnChainOracles } from '../types'; +import { OffChainOracle, OffChainOracles, OnChainOracle, OnChainOracles } from '@/services' const ethgasstation: OffChainOracle = { name: 'ethgasstation', @@ -9,7 +9,7 @@ const ethgasstation: OffChainOracle = { lowPropertyName: 'safeLow', denominator: 10, additionalDataProperty: null, -}; +} const etherchain: OffChainOracle = { name: 'etherchain', @@ -20,49 +20,25 @@ const etherchain: OffChainOracle = { lowPropertyName: 'slow', denominator: 1e9, additionalDataProperty: 'data', -}; - -// const blockscout: OffChainOracle = { -// name: 'blockscout', -// url: 'https://blockscout.com/eth/mainnet/api/v1/gas-price-oracle', -// instantPropertyName: 'fast', -// fastPropertyName: 'average', -// standardPropertyName: 'slow', -// lowPropertyName: 'slow', -// denominator: 1, -// additionalDataProperty: null, -// }; - -// const anyblock: OffChainOracle = { -// name: 'anyblock', -// url: 'https://api.anyblock.tools/ethereum/latest-minimum-gasprice', -// instantPropertyName: 'instant', -// fastPropertyName: 'fast', -// standardPropertyName: 'standard', -// lowPropertyName: 'slow', -// denominator: 1, -// additionalDataProperty: null, -// }; +} const chainlink: OnChainOracle = { name: 'chainlink', callData: '0x50d25bcd', contract: '0x169E633A2D1E6c10dD91238Ba11c4A708dfEF37C', denominator: '1000000000', -}; +} export const offChainOracles: OffChainOracles = { ethgasstation, - // anyblock, - // blockscout, etherchain, -}; +} export const onChainOracles: OnChainOracles = { chainlink, -}; +} export default { offChainOracles, onChainOracles, -}; +} diff --git a/src/config/optimism.ts b/src/config/optimism.ts new file mode 100644 index 0000000..36cdc4a --- /dev/null +++ b/src/config/optimism.ts @@ -0,0 +1,18 @@ +import { OffChainOracles, OnChainOracle, OnChainOracles } from '@/services' + +export const offChainOracles: OffChainOracles = {} + +const optimism: OnChainOracle = { + name: 'optimism', + callData: '0xfe173b97', + denominator: '1000000000', + contract: '0x420000000000000000000000000000000000000F', +} +export const onChainOracles: OnChainOracles = { + optimism, +} + +export default { + offChainOracles, + onChainOracles, +} diff --git a/src/config/polygon.ts b/src/config/polygon.ts index d75240a..04fe8ce 100644 --- a/src/config/polygon.ts +++ b/src/config/polygon.ts @@ -1,4 +1,4 @@ -import { OffChainOracle, OffChainOracles, OnChainOracles } from '../types'; +import { OffChainOracle, OffChainOracles, OnChainOracles } from '@/services' const maticGasStation: OffChainOracle = { name: 'maticGasStation', @@ -9,15 +9,15 @@ const maticGasStation: OffChainOracle = { lowPropertyName: 'safeLow', denominator: 1, additionalDataProperty: null, -}; +} export const offChainOracles: OffChainOracles = { maticGasStation, -}; +} -export const onChainOracles: OnChainOracles = {}; +export const onChainOracles: OnChainOracles = {} export default { offChainOracles, onChainOracles, -}; +} diff --git a/src/config/xdai.ts b/src/config/xdai.ts index dd4d02a..9133848 100644 --- a/src/config/xdai.ts +++ b/src/config/xdai.ts @@ -1,4 +1,4 @@ -import { OffChainOracle, OffChainOracles, OnChainOracles } from '../types'; +import { OffChainOracle, OffChainOracles, OnChainOracles } from '@/services' const blockscout: OffChainOracle = { name: 'blockscout', @@ -9,15 +9,15 @@ const blockscout: OffChainOracle = { lowPropertyName: 'slow', denominator: 1, additionalDataProperty: null, -}; +} export const offChainOracles: OffChainOracles = { blockscout, -}; +} -export const onChainOracles: OnChainOracles = {}; +export const onChainOracles: OnChainOracles = {} export default { offChainOracles, onChainOracles, -}; +} diff --git a/src/constants/index.ts b/src/constants/index.ts new file mode 100644 index 0000000..9adc545 --- /dev/null +++ b/src/constants/index.ts @@ -0,0 +1,14 @@ +import BigNumber from 'bignumber.js' + +const GWEI = 1e9 +const DEFAULT_TIMEOUT = 10000 + +const ROUND_UP = 1 +const ROUND_DOWN = 2 +const GWEI_PRECISION = 9 +const INT_PRECISION = 0 + +const SUCCESS_STATUS = 200 +const BG_ZERO = new BigNumber(0) +const PERCENT_MULTIPLIER = 100 +export { GWEI, DEFAULT_TIMEOUT, ROUND_UP, ROUND_DOWN, GWEI_PRECISION, INT_PRECISION, SUCCESS_STATUS, BG_ZERO, PERCENT_MULTIPLIER } diff --git a/src/index.ts b/src/index.ts index 4100a35..aae5905 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,278 +1 @@ -import axios from 'axios'; -import BigNumber from 'bignumber.js'; - -import { ChainId, NETWORKS } from './config'; - -import { - Config, - Options, - GasPrice, - GasPriceKey, - OffChainOracle, - OnChainOracle, - OnChainOracles, - OffChainOracles, -} from './types'; - -const defaultFastGas = 22; -export class GasPriceOracle { - lastGasPrice: GasPrice; - offChainOracles: OffChainOracles = {}; - onChainOracles: OnChainOracles = {}; - configuration: Config = { - chainId: ChainId.MAINNET, - defaultRpc: 'https://api.mycryptoapi.com/eth', - timeout: 10000, - defaultFallbackGasPrices: { - instant: defaultFastGas * 1.3, - fast: defaultFastGas, - standard: defaultFastGas * 0.85, - low: defaultFastGas * 0.5, - }, - }; - - constructor(options?: Options) { - if (options) { - Object.assign(this.configuration, options); - } - - this.configuration.defaultFallbackGasPrices = this.normalize(this.configuration.defaultFallbackGasPrices); - - const network = NETWORKS[this.configuration.chainId]; - - if (network) { - const { offChainOracles, onChainOracles } = network; - this.offChainOracles = { ...offChainOracles }; - this.onChainOracles = { ...onChainOracles }; - } - } - - async askOracle(oracle: OffChainOracle): Promise { - const { - name, - url, - instantPropertyName, - fastPropertyName, - standardPropertyName, - lowPropertyName, - denominator, - additionalDataProperty, - } = oracle; - const response = await axios.get(url, { timeout: this.configuration.timeout }); - if (response.status === 200) { - const gas = additionalDataProperty ? response.data[additionalDataProperty] : response.data; - if (Number(gas[fastPropertyName]) === 0) { - throw new Error(`${name} oracle provides corrupted values`); - } - const gasPrices: GasPrice = { - instant: parseFloat(gas[instantPropertyName]) / denominator, - fast: parseFloat(gas[fastPropertyName]) / denominator, - standard: parseFloat(gas[standardPropertyName]) / denominator, - low: parseFloat(gas[lowPropertyName]) / denominator, - }; - return this.normalize(gasPrices); - } else { - throw new Error(`Fetch gasPrice from ${name} oracle failed. Trying another one...`); - } - } - async fetchGasPricesOffChain(): Promise { - for (const oracle of Object.values(this.offChainOracles)) { - try { - return await this.askOracle(oracle); - } catch (e) { - console.info(e.message); - continue; - } - } - throw new Error('All oracles are down. Probably a network error.'); - } - - async fetchMedianGasPriceOffChain(): Promise { - const promises: Promise[] = []; - for (const oracle of Object.values(this.offChainOracles) as Array) { - promises.push(this.askOracle(oracle)); - } - - const settledPromises = await Promise.allSettled(promises); - const allGasPrices = settledPromises.reduce((acc: GasPrice[], result) => { - if (result.status === 'fulfilled') { - acc.push(result.value); - return acc; - } - return acc; - }, []); - - if (allGasPrices.length === 0) { - throw new Error('All oracles are down. Probably a network error.'); - } - return this.median(allGasPrices); - } - - median(gasPrices: GasPrice[]): GasPrice { - const medianGasPrice: GasPrice = { instant: 0, fast: 0, standard: 0, low: 0 }; - - const results: { [key in GasPriceKey]: number[] } = { - instant: [], - fast: [], - standard: [], - low: [], - }; - - for (const gasPrice of gasPrices) { - results.instant.push(gasPrice.instant); - results.fast.push(gasPrice.fast); - results.standard.push(gasPrice.standard); - results.low.push(gasPrice.low); - } - - for (const type of Object.keys(medianGasPrice) as Array) { - const allPrices = results[type].sort((a, b) => a - b); - if (allPrices.length === 1) { - medianGasPrice[type] = allPrices[0]; - continue; - } else if (allPrices.length === 0) { - continue; - } - const isEven = allPrices.length % 2 === 0; - const middle = Math.floor(allPrices.length / 2); - medianGasPrice[type] = isEven ? (allPrices[middle - 1] + allPrices[middle]) / 2.0 : allPrices[middle]; - } - return this.normalize(medianGasPrice); - } - /** - * Normalizes GasPrice values to Gwei. No more than 9 decimals basically - * @param GasPrice _gas - */ - normalize(_gas: GasPrice): GasPrice { - const format = { - decimalSeparator: '.', - groupSeparator: '', - }; - const decimals = 9; - - const gas: GasPrice = { ..._gas }; - for (const type of Object.keys(gas) as Array) { - gas[type] = Number(new BigNumber(gas[type]).toFormat(decimals, format)); - } - - return gas; - } - - async fetchGasPricesOnChain(): Promise { - for (const oracle of Object.values(this.onChainOracles)) { - const { name, callData, contract, denominator, rpc } = oracle; - const rpcUrl = rpc || this.configuration.defaultRpc; - const body = { - jsonrpc: '2.0', - id: 1337, - method: 'eth_call', - params: [{ data: callData, to: contract }, 'latest'], - }; - try { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const response = await axios.post(rpcUrl!, body, { timeout: this.configuration.timeout }); - if (response.status === 200) { - const { result } = response.data; - let fastGasPrice = new BigNumber(result); - if (fastGasPrice.isZero()) { - throw new Error(`${name} oracle provides corrupted values`); - } - fastGasPrice = fastGasPrice.div(denominator); - return fastGasPrice.toNumber(); - } else { - throw new Error(`Fetch gasPrice from ${name} oracle failed. Trying another one...`); - } - } catch (e) { - console.error(e.message); - } - } - throw new Error('All oracles are down. Probably a network error.'); - } - - async fetchGasPriceFromRpc(): Promise { - const rpcUrl = this.configuration.defaultRpc; - const body = { - jsonrpc: '2.0', - id: 1337, - method: 'eth_gasPrice', - params: [], - }; - try { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const response = await axios.post(rpcUrl!, body, { timeout: this.configuration.timeout }); - if (response.status === 200) { - const { result } = response.data; - let fastGasPrice = new BigNumber(result); - if (fastGasPrice.isZero()) { - throw new Error(`Default RPC provides corrupted values`); - } - fastGasPrice = fastGasPrice.div(1e9); - return fastGasPrice.toNumber(); - } - - throw new Error(`Fetch gasPrice from default RPC failed..`); - } catch (e) { - console.error(e.message); - throw new Error('Default RPC is down. Probably a network error.'); - } - } - - async gasPrices(fallbackGasPrices?: GasPrice, median = true): Promise { - this.lastGasPrice = this.lastGasPrice || fallbackGasPrices || this.configuration.defaultFallbackGasPrices; - - if (Object.keys(this.offChainOracles).length > 0) { - try { - this.lastGasPrice = median - ? await this.fetchMedianGasPriceOffChain() - : await this.fetchGasPricesOffChain(); - return this.lastGasPrice; - } catch (e) { - console.log('Failed to fetch gas prices from offchain oracles...'); - } - } - - if (Object.keys(this.onChainOracles).length > 0) { - try { - const fastGas = await this.fetchGasPricesOnChain(); - this.lastGasPrice = this.categorize(fastGas); - return this.lastGasPrice; - } catch (e) { - console.log('Failed to fetch gas prices from onchain oracles...'); - } - } - - try { - const fastGas = await this.fetchGasPriceFromRpc(); - this.lastGasPrice = this.categorize(fastGas); - return this.lastGasPrice; - } catch (e) { - console.log('Failed to fetch gas prices from default RPC. Last known gas will be returned'); - } - return this.normalize(this.lastGasPrice); - } - - categorize(gasPrice: number): GasPrice { - return this.normalize({ - instant: gasPrice * 1.3, - fast: gasPrice, - standard: gasPrice * 0.85, - low: gasPrice * 0.5, - }); - } - - addOffChainOracle(oracle: OffChainOracle): void { - this.offChainOracles[oracle.name] = oracle; - } - - addOnChainOracle(oracle: OnChainOracle): void { - this.onChainOracles[oracle.name] = oracle; - } - - removeOnChainOracle(name: string): void { - delete this.onChainOracles[name]; - } - - removeOffChainOracle(name: string): void { - delete this.offChainOracles[name]; - } -} +export * from '@/services/gas-price-oracle' diff --git a/src/services/gas-estimation/constants.ts b/src/services/gas-estimation/constants.ts new file mode 100644 index 0000000..32fe046 --- /dev/null +++ b/src/services/gas-estimation/constants.ts @@ -0,0 +1,26 @@ +// How many blocks to consider for priority fee estimation +import BigNumber from 'bignumber.js' +import { EstimatedGasPrice } from './types' + +const FEE_HISTORY_BLOCKS = 10 +// Which percentile of effective priority fees to include +const FEE_HISTORY_PERCENTILE = 5 + +const DEFAULT_BASE_FEE = 20 +const DEFAULT_PRIORITY_FEE = 3 +const PRIORITY_FEE_INCREASE_BOUNDARY = 200 // % + +const FALLBACK_ESTIMATE: EstimatedGasPrice = { + baseFee: DEFAULT_BASE_FEE, + maxPriorityFeePerGas: DEFAULT_PRIORITY_FEE, + maxFeePerGas: new BigNumber(DEFAULT_PRIORITY_FEE).plus(DEFAULT_BASE_FEE).toNumber(), +} + +export { + DEFAULT_BASE_FEE, + FALLBACK_ESTIMATE, + FEE_HISTORY_BLOCKS, + DEFAULT_PRIORITY_FEE, + FEE_HISTORY_PERCENTILE, + PRIORITY_FEE_INCREASE_BOUNDARY, +} diff --git a/src/services/gas-estimation/eip1559.ts b/src/services/gas-estimation/eip1559.ts new file mode 100644 index 0000000..baa2052 --- /dev/null +++ b/src/services/gas-estimation/eip1559.ts @@ -0,0 +1,137 @@ +import BigNumber from 'bignumber.js' + +import { FeeHistory, Block } from '@/types' +import { Config, EstimateOracle, EstimatedGasPrice, CalculateFeesParams, GasEstimationOptionsPayload } from './types' + +import { RpcFetcher } from '@/services' +import { ChainId, NETWORKS } from '@/config' +import { BG_ZERO, PERCENT_MULTIPLIER } from '@/constants' +import { findMax, fromNumberToHex, fromWeiToGwei, getMedian } from '@/utils' + +import { DEFAULT_PRIORITY_FEE, PRIORITY_FEE_INCREASE_BOUNDARY, FEE_HISTORY_BLOCKS, FEE_HISTORY_PERCENTILE } from './constants' + +// !!! MAKE SENSE ALL CALCULATIONS IN GWEI !!! +export class Eip1559GasPriceOracle implements EstimateOracle { + public configuration: Config = { + chainId: ChainId.MAINNET, + blocksCount: NETWORKS[ChainId.MAINNET].blocksCount, + percentile: NETWORKS[ChainId.MAINNET].percentile, + fallbackGasPrices: undefined, + } + private fetcher: RpcFetcher + + constructor({ fetcher, ...options }: GasEstimationOptionsPayload) { + this.fetcher = fetcher + const chainId = options?.chainId || this.configuration.chainId + this.configuration.blocksCount = NETWORKS[chainId]?.blocksCount || FEE_HISTORY_BLOCKS + this.configuration.percentile = NETWORKS[chainId]?.percentile || FEE_HISTORY_PERCENTILE + + if (options) { + this.configuration = { ...this.configuration, ...options } + } + } + + public async estimateFees(fallbackGasPrices?: EstimatedGasPrice): Promise { + try { + const { data: latestBlock } = await this.fetcher.makeRpcCall<{ result: Block }>({ + method: 'eth_getBlockByNumber', + params: ['latest', false], + }) + + if (!latestBlock.result.baseFeePerGas) { + throw new Error('An error occurred while fetching current base fee, falling back') + } + + const baseFee = fromWeiToGwei(latestBlock.result.baseFeePerGas) + + const blockCount = fromNumberToHex(this.configuration.blocksCount) + const rewardPercentiles: number[] = [this.configuration.percentile] + + const { data } = await this.fetcher.makeRpcCall<{ result: FeeHistory }>({ + method: 'eth_feeHistory', + params: [blockCount, 'latest', rewardPercentiles], + }) + + return this.calculateFees({ baseFee, feeHistory: data.result }) + } catch (err) { + if (fallbackGasPrices) { + return fallbackGasPrices + } + if (this.configuration.fallbackGasPrices) { + return this.configuration.fallbackGasPrices + } + throw err + } + } + + private calculatePriorityFeeEstimate(feeHistory?: FeeHistory) { + if (!feeHistory) { + return null + } + + const rewards = feeHistory.reward + ?.map((r) => fromWeiToGwei(r[0])) + .filter((r) => r.isGreaterThan(0)) + .sort() + + if (!rewards) { + return null + } + + // Calculate percentage increases from between ordered list of fees + const percentageIncreases = rewards.reduce((acc, curr, i, arr) => { + if (i !== arr.length - 1) { + const next = arr[i + 1] + const percentageIncrease = next.minus(curr).dividedBy(curr).multipliedBy(PERCENT_MULTIPLIER) + acc.push(percentageIncrease) + } + + return acc + }, []) + + const { highest, index } = findMax(percentageIncreases) + // If we have big increased in value, we could be considering "outliers" in our estimate + // Skip the low elements and take a new median + const values = + highest.isGreaterThanOrEqualTo(PRIORITY_FEE_INCREASE_BOUNDARY) && index >= getMedian(rewards) + ? rewards.slice(index) + : rewards + + return values[getMedian(values)] + } + + private async getPriorityFromChain(feeHistory?: FeeHistory) { + try { + const { data } = await this.fetcher.makeRpcCall<{ result: string }>({ + method: 'eth_maxPriorityFeePerGas', + params: [], + }) + + return fromWeiToGwei(data.result) + } catch (err) { + return this.calculatePriorityFeeEstimate(feeHistory) + } + } + + private async calculateFees({ baseFee, feeHistory }: CalculateFeesParams): Promise { + const estimatedPriorityFee = await this.getPriorityFromChain(feeHistory) + + const { highest: maxPriorityFeePerGas } = findMax([estimatedPriorityFee ?? BG_ZERO, new BigNumber(DEFAULT_PRIORITY_FEE)]) + + const maxFeePerGas = baseFee.plus(maxPriorityFeePerGas) + + if (this.checkIsGreaterThanMax(maxFeePerGas) || this.checkIsGreaterThanMax(maxPriorityFeePerGas)) { + throw new Error('Estimated gas fee was much higher than expected, erroring') + } + + return { + baseFee: baseFee.toNumber(), + maxFeePerGas: maxFeePerGas.toNumber(), + maxPriorityFeePerGas: maxPriorityFeePerGas.toNumber(), + } + } + + private checkIsGreaterThanMax(value: BigNumber): boolean { + return value.isGreaterThanOrEqualTo(NETWORKS[this.configuration.chainId]?.maxGasPrice) || false + } +} diff --git a/src/services/gas-estimation/index.ts b/src/services/gas-estimation/index.ts new file mode 100644 index 0000000..8885838 --- /dev/null +++ b/src/services/gas-estimation/index.ts @@ -0,0 +1,2 @@ +export * from './eip1559' +export * from './types' diff --git a/src/services/gas-estimation/types.ts b/src/services/gas-estimation/types.ts new file mode 100644 index 0000000..c54474f --- /dev/null +++ b/src/services/gas-estimation/types.ts @@ -0,0 +1,37 @@ +import BigNumber from 'bignumber.js' + +import { FeeHistory } from '@/types' +import { RpcFetcher } from '@/services' + +export type EstimatedGasPrice = { + maxFeePerGas: number + baseFee: number | undefined + maxPriorityFeePerGas: number +} + +export type EstimateFeesParams = { + blocksCount: number + percentile: number +} + +export type CalculateFeesParams = { + baseFee: BigNumber + feeHistory?: FeeHistory +} + +export type Options = { + chainId?: number + blocksCount?: number + percentile?: number + fallbackGasPrices: EstimatedGasPrice | undefined +} + +export type GasEstimationOptionsPayload = Options & { + fetcher: RpcFetcher +} + +export type Config = Required & { fallbackGasPrices?: EstimatedGasPrice } +export abstract class EstimateOracle { + public configuration: Config + public abstract estimateFees(fallbackGasPrices?: EstimatedGasPrice): Promise +} diff --git a/src/services/gas-price-oracle/gas-price-oracle.ts b/src/services/gas-price-oracle/gas-price-oracle.ts new file mode 100644 index 0000000..8ad6530 --- /dev/null +++ b/src/services/gas-price-oracle/gas-price-oracle.ts @@ -0,0 +1,96 @@ +import { + GasOracleOptions, + GasPricesWithEstimateInput, + GasPriceWithEstimate, + GetGasPriceInput, + GetTxGasParamsInput, + GetTxGasParamsRes, + OracleProvider, +} from './types' + +import { ChainId, NETWORKS } from '@/config' +import { DEFAULT_TIMEOUT } from '@/constants' +import { bumpOnPercent, fromGweiToWeiHex } from '@/utils' + +import { + RpcFetcher, + GasPrice, + LegacyOracle, + EstimateOracle, + EstimatedGasPrice, + LegacyGasPriceOracle, + Eip1559GasPriceOracle, +} from '@/services' + +export class GasPriceOracle implements OracleProvider { + public eip1559: EstimateOracle + public legacy: LegacyOracle + public fetcher: RpcFetcher + private chainId: ChainId + public constructor(options?: GasOracleOptions) { + const timeout = options?.timeout ?? DEFAULT_TIMEOUT + this.chainId = options?.chainId || ChainId.MAINNET + const defaultRpc = options?.defaultRpc || NETWORKS[this.chainId].rpcUrl + + this.fetcher = new RpcFetcher(defaultRpc, timeout) + + const { gasPrices, estimated } = options?.fallbackGasPrices || {} + + const payload = { ...options, fetcher: this.fetcher } + this.legacy = new LegacyGasPriceOracle({ + ...payload, + fallbackGasPrices: gasPrices, + }) + + this.eip1559 = new Eip1559GasPriceOracle({ + ...payload, + fallbackGasPrices: estimated, + }) + } + + public async gasPrices(payload: GetGasPriceInput = {}): Promise { + const { fallbackGasPrices, shouldGetMedian, isLegacy = false } = payload + if (isLegacy) { + return await this.legacy.gasPrices(fallbackGasPrices?.gasPrices, shouldGetMedian) + } + try { + return await this.eip1559.estimateFees(fallbackGasPrices?.estimated) + } catch { + return await this.legacy.gasPrices(fallbackGasPrices?.gasPrices, shouldGetMedian) + } + } + + public async getTxGasParams(payload: GetTxGasParamsInput = {}): Promise { + const { fallbackGasPrices, shouldGetMedian, isLegacy = false, bumpPercent = 0, legacySpeed = 'fast' } = payload + + if (isLegacy) { + const legacyGasPrice = await this.legacy.gasPrices(fallbackGasPrices?.gasPrices, shouldGetMedian) + + return { gasPrice: fromGweiToWeiHex(bumpOnPercent(legacyGasPrice[legacySpeed], bumpPercent)) } + } + + try { + const eipParams = await this.eip1559.estimateFees(fallbackGasPrices?.estimated) + return { + maxFeePerGas: fromGweiToWeiHex(bumpOnPercent(eipParams.maxFeePerGas, bumpPercent)), + maxPriorityFeePerGas: fromGweiToWeiHex(bumpOnPercent(eipParams.maxPriorityFeePerGas, bumpPercent)), + } + } catch { + const legacyGasPrice = await this.legacy.gasPrices(fallbackGasPrices?.gasPrices, shouldGetMedian) + + return { gasPrice: fromGweiToWeiHex(bumpOnPercent(legacyGasPrice[legacySpeed], bumpPercent)) } + } + } + + public async gasPricesWithEstimate(payload: GasPricesWithEstimateInput = {}): Promise { + const { fallbackGasPrices, shouldGetMedian } = payload + + const estimate = await this.eip1559.estimateFees(fallbackGasPrices?.estimated) + const gasPrices = await this.legacy.gasPrices(fallbackGasPrices?.gasPrices, shouldGetMedian) + + return { + estimate, + gasPrices, + } + } +} diff --git a/src/services/gas-price-oracle/index.ts b/src/services/gas-price-oracle/index.ts new file mode 100644 index 0000000..b90ee2e --- /dev/null +++ b/src/services/gas-price-oracle/index.ts @@ -0,0 +1,2 @@ +export * from './gas-price-oracle' +export * from './types' diff --git a/src/services/gas-price-oracle/types.ts b/src/services/gas-price-oracle/types.ts new file mode 100644 index 0000000..49b9ed9 --- /dev/null +++ b/src/services/gas-price-oracle/types.ts @@ -0,0 +1,54 @@ +import { RpcFetcher, GasPrice, LegacyOracle, EstimatedGasPrice, EstimateOracle, GasPriceKey } from '@/services' + +export type GetTxGasParamsInput = GetGasPriceInput & { + bumpPercent?: number + legacySpeed?: GasPriceKey +} + +export type GetTxGasParamsRes = + | { + gasPrice: string + } + | { + maxFeePerGas: string + maxPriorityFeePerGas: string + } + +export type GetGasPriceInput = { + isLegacy?: boolean + shouldGetMedian?: boolean + fallbackGasPrices?: FallbackGasPrices +} + +export type FallbackGasPrices = { + gasPrices?: GasPrice + estimated?: EstimatedGasPrice +} + +export type GasPricesWithEstimateInput = { + shouldGetMedian?: boolean + fallbackGasPrices?: FallbackGasPrices +} + +export type GasOracleOptions = { + chainId?: number + timeout?: number + defaultRpc?: string + blocksCount?: number + percentile?: number + fallbackGasPrices?: FallbackGasPrices +} + +export type GasPriceWithEstimate = { + gasPrices: GasPrice + estimate: EstimatedGasPrice +} + +export interface OracleProvider { + eip1559: EstimateOracle + legacy: LegacyOracle + fetcher: RpcFetcher + gasPrices: (payload: GetGasPriceInput) => Promise + gasPricesWithEstimate: (payload: GasPricesWithEstimateInput) => Promise + getTxGasParams: (payload: GetTxGasParamsInput) => Promise +} diff --git a/src/services/index.ts b/src/services/index.ts new file mode 100644 index 0000000..89c2f2d --- /dev/null +++ b/src/services/index.ts @@ -0,0 +1,6 @@ +export * from './gas-price-oracle' + +export * from './gas-estimation' +export * from './legacy-gas-price' + +export * from './rpcFetcher' diff --git a/src/services/legacy-gas-price/constants.ts b/src/services/legacy-gas-price/constants.ts new file mode 100644 index 0000000..993f717 --- /dev/null +++ b/src/services/legacy-gas-price/constants.ts @@ -0,0 +1,10 @@ +const DEFAULT_GAS_PRICE = { instant: 0, fast: 0, standard: 0, low: 0 } + +const MULTIPLIERS = { + instant: 1.3, + standard: 0.85, + low: 0.5, + fast: 1, +} + +export { MULTIPLIERS, DEFAULT_GAS_PRICE } diff --git a/src/services/legacy-gas-price/index.ts b/src/services/legacy-gas-price/index.ts new file mode 100644 index 0000000..8fa88b3 --- /dev/null +++ b/src/services/legacy-gas-price/index.ts @@ -0,0 +1,2 @@ +export * from './legacy' +export * from './types' diff --git a/src/services/legacy-gas-price/legacy.ts b/src/services/legacy-gas-price/legacy.ts new file mode 100644 index 0000000..514620f --- /dev/null +++ b/src/services/legacy-gas-price/legacy.ts @@ -0,0 +1,292 @@ +import axios from 'axios' +import BigNumber from 'bignumber.js' + +import { + GasPrice, + GasPriceKey, + LegacyOracle, + OnChainOracle, + OffChainOracle, + LegacyOptions, + OnChainOracles, + OffChainOracles, + LegacyOptionsPayload, + GetGasPriceFromRespInput, +} from './types' + +import { RpcFetcher } from '@/services' +import { ChainId, NETWORKS } from '@/config' +import { GWEI, DEFAULT_TIMEOUT, GWEI_PRECISION } from '@/constants' + +import { MULTIPLIERS, DEFAULT_GAS_PRICE } from './constants' + +export class LegacyGasPriceOracle implements LegacyOracle { + static getMedianGasPrice(gasPrices: GasPrice[]): GasPrice { + const medianGasPrice: GasPrice = DEFAULT_GAS_PRICE + + const results: Record = { + instant: [], + fast: [], + standard: [], + low: [], + } + + for (const gasPrice of gasPrices) { + results.instant.push(gasPrice.instant) + results.fast.push(gasPrice.fast) + results.standard.push(gasPrice.standard) + results.low.push(gasPrice.low) + } + + for (const type of Object.keys(medianGasPrice) as (keyof GasPrice)[]) { + const allPrices = results[type].sort((a, b) => a - b) + if (allPrices.length === 1) { + medianGasPrice[type] = allPrices[0] + continue + } else if (allPrices.length === 0) { + continue + } + const isEven = allPrices.length % 2 === 0 + const middle = Math.floor(allPrices.length / 2) + medianGasPrice[type] = isEven ? (allPrices[middle - 1] + allPrices[middle]) / 2.0 : allPrices[middle] + } + + return LegacyGasPriceOracle.normalize(medianGasPrice) + } + + static getMultipliedPrices(gasPrice: number): GasPrice { + return { + instant: gasPrice * MULTIPLIERS.instant, + fast: gasPrice * MULTIPLIERS.fast, + standard: gasPrice * MULTIPLIERS.standard, + low: gasPrice * MULTIPLIERS.low, + } + } + + static normalize(_gas: GasPrice): GasPrice { + const format = { + groupSeparator: '', + decimalSeparator: '.', + } + + const gas: GasPrice = { ..._gas } + for (const type of Object.keys(gas) as (keyof GasPrice)[]) { + gas[type] = Number(new BigNumber(gas[type]).toFormat(GWEI_PRECISION, format)) + } + + return gas + } + + static getCategorize(gasPrice: number): GasPrice { + return LegacyGasPriceOracle.normalize(LegacyGasPriceOracle.getMultipliedPrices(gasPrice)) + } + + static getGasPriceFromResponse(payload: GetGasPriceFromRespInput): number { + const { response, fetcherName, denominator = GWEI } = payload + let fastGasPrice = new BigNumber(response) + if (fastGasPrice.isZero()) { + throw new Error(`${fetcherName} provides corrupted values`) + } + fastGasPrice = fastGasPrice.div(denominator) + return fastGasPrice.toNumber() + } + + public lastGasPrice: GasPrice + public onChainOracles: OnChainOracles = {} + public offChainOracles: OffChainOracles = {} + public configuration: Required = { + chainId: ChainId.MAINNET, + timeout: DEFAULT_TIMEOUT, + defaultRpc: NETWORKS[ChainId.MAINNET].rpcUrl, + fallbackGasPrices: LegacyGasPriceOracle.getMultipliedPrices(NETWORKS[ChainId.MAINNET].defaultGasPrice), + } + + private readonly fetcher: RpcFetcher + + constructor({ fetcher, ...options }: LegacyOptionsPayload) { + this.fetcher = fetcher + if (options) { + this.configuration = { ...this.configuration, ...options } + } + + const fallbackGasPrices = + this.configuration.fallbackGasPrices || LegacyGasPriceOracle.getMultipliedPrices(NETWORKS[ChainId.MAINNET].defaultGasPrice) + this.configuration.fallbackGasPrices = LegacyGasPriceOracle.normalize(fallbackGasPrices) + + const network = NETWORKS[this.configuration.chainId]?.oracles + if (network) { + this.offChainOracles = { ...network.offChainOracles } + this.onChainOracles = { ...network.onChainOracles } + } + } + + public addOffChainOracle(oracle: OffChainOracle): void { + this.offChainOracles[oracle.name] = oracle + } + + public addOnChainOracle(oracle: OnChainOracle): void { + this.onChainOracles[oracle.name] = oracle + } + + public removeOnChainOracle(name: string): void { + delete this.onChainOracles[name] + } + + public removeOffChainOracle(name: string): void { + delete this.offChainOracles[name] + } + + public async fetchGasPricesOnChain(): Promise { + for (const oracle of Object.values(this.onChainOracles)) { + const { name, callData, contract, denominator, rpc } = oracle + + try { + const response = await this.fetcher.makeRpcCall<{ result: string | number }>({ + rpc, + method: 'eth_call', + params: [{ data: callData, to: contract }, 'latest'], + }) + + if (response.status === 200) { + return LegacyGasPriceOracle.getGasPriceFromResponse({ + denominator, + fetcherName: `${name} oracle`, + response: response.data.result, + }) + } + throw new Error(`Fetch gasPrice from ${name} oracle failed. Trying another one...`) + } catch (e) { + console.error(e.message) + } + } + throw new Error('All oracles are down. Probably a network error.') + } + + public async fetchGasPriceFromRpc(): Promise { + try { + const { status, data } = await this.fetcher.makeRpcCall<{ result: string | number }>({ + params: [], + method: 'eth_gasPrice', + }) + + if (status === 200) { + return LegacyGasPriceOracle.getGasPriceFromResponse({ + fetcherName: 'Default RPC', + response: data.result, + }) + } + + throw new Error(`Fetch gasPrice from default RPC failed..`) + } catch (e) { + console.error(e.message) + throw new Error('Default RPC is down. Probably a network error.') + } + } + + public async fetchGasPricesOffChain(shouldGetMedian = true): Promise { + if (shouldGetMedian) { + return await this.fetchMedianGasPriceOffChain() + } + + for (const oracle of Object.values(this.offChainOracles)) { + try { + return await this.askOracle(oracle) + } catch (e) { + console.info(`${oracle} has error - `, e.message) + continue + } + } + throw new Error('All oracles are down. Probably a network error.') + } + + public async fetchMedianGasPriceOffChain(): Promise { + const promises: Promise[] = [] + + for (const oracle of Object.values(this.offChainOracles) as OffChainOracle[]) { + promises.push(this.askOracle(oracle)) + } + + const settledPromises = await Promise.allSettled(promises) + + const allGasPrices = settledPromises.reduce((acc: GasPrice[], result) => { + if (result.status === 'fulfilled') { + acc.push(result.value) + return acc + } + return acc + }, []) + + if (allGasPrices.length === 0) { + throw new Error('All oracles are down. Probably a network error.') + } + + return LegacyGasPriceOracle.getMedianGasPrice(allGasPrices) + } + + public async gasPrices(fallbackGasPrices?: GasPrice, shouldGetMedian = true): Promise { + if (!this.lastGasPrice) { + this.lastGasPrice = fallbackGasPrices || this.configuration.fallbackGasPrices + } + + if (Object.keys(this.offChainOracles).length > 0) { + try { + this.lastGasPrice = await this.fetchGasPricesOffChain(shouldGetMedian) + return this.lastGasPrice + } catch (e) { + console.error('Failed to fetch gas prices from offchain oracles...') + } + } + + if (Object.keys(this.onChainOracles).length > 0) { + try { + const fastGas = await this.fetchGasPricesOnChain() + this.lastGasPrice = LegacyGasPriceOracle.getCategorize(fastGas) + return this.lastGasPrice + } catch (e) { + console.error('Failed to fetch gas prices from onchain oracles...') + } + } + + try { + const fastGas = await this.fetchGasPriceFromRpc() + this.lastGasPrice = LegacyGasPriceOracle.getCategorize(fastGas) + return this.lastGasPrice + } catch (e) { + console.error('Failed to fetch gas prices from default RPC. Last known gas will be returned') + } + return LegacyGasPriceOracle.normalize(this.lastGasPrice) + } + + public async askOracle(oracle: OffChainOracle): Promise { + const { + url, + name, + denominator, + lowPropertyName, + fastPropertyName, + instantPropertyName, + standardPropertyName, + additionalDataProperty, + } = oracle + + const response = await axios.get(url, { timeout: this.configuration.timeout }) + + if (response.status === 200) { + const gas = additionalDataProperty ? response.data[additionalDataProperty] : response.data + + if (Number(gas[fastPropertyName]) === 0) { + throw new Error(`${name} oracle provides corrupted values`) + } + + const gasPrices: GasPrice = { + instant: parseFloat(gas[instantPropertyName]) / denominator, + fast: parseFloat(gas[fastPropertyName]) / denominator, + standard: parseFloat(gas[standardPropertyName]) / denominator, + low: parseFloat(gas[lowPropertyName]) / denominator, + } + return LegacyGasPriceOracle.normalize(gasPrices) + } else { + throw new Error(`Fetch gasPrice from ${name} oracle failed. Trying another one...`) + } + } +} diff --git a/src/services/legacy-gas-price/types.ts b/src/services/legacy-gas-price/types.ts new file mode 100644 index 0000000..c81759d --- /dev/null +++ b/src/services/legacy-gas-price/types.ts @@ -0,0 +1,78 @@ +import { RpcFetcher } from '@/services' + +export type OffChainOracle = { + url: string + name: string + denominator: number + lowPropertyName: string + fastPropertyName: string + instantPropertyName: string + standardPropertyName: string + additionalDataProperty: string | null +} + +export type OffChainOracles = Record + +export type OnChainOracle = { + name: string + rpc?: string + contract: string + callData: string + denominator: string +} + +export type OnChainOracles = Record + +export type AllOracles = { + onChainOracles: OnChainOracles + offChainOracles: OffChainOracles +} + +export type NetworkConfig = Record + +export type GasPriceKey = 'instant' | 'fast' | 'standard' | 'low' +export type GasPrice = Record + +export type LegacyOptions = { + chainId?: number + timeout?: number + defaultRpc?: string + fallbackGasPrices?: GasPrice +} + +export type LegacyOptionsPayload = LegacyOptions & { + fetcher: RpcFetcher +} + +export type GetGasPriceFromRespInput = { + fetcherName: string + response: string | number + denominator?: number | string +} + +type Config = Required + +export abstract class LegacyOracle { + static normalize: (_gas: GasPrice) => GasPrice + static getCategorize: (gasPrice: number) => GasPrice + static getMultipliedPrices: (gasPrice: number) => GasPrice + static getMedianGasPrice: (gasPrices: GasPrice[]) => GasPrice + static getGasPriceFromResponse: (payload: GetGasPriceFromRespInput) => Promise + + public configuration: Config + public lastGasPrice: GasPrice + public onChainOracles: OnChainOracles + public offChainOracles: OffChainOracles + + public abstract removeOnChainOracle(name: string): void + public abstract removeOffChainOracle(name: string): void + public abstract addOnChainOracle(oracle: OnChainOracle): void + public abstract addOffChainOracle(oracle: OffChainOracle): void + + public fetchGasPriceFromRpc: () => Promise + public fetchGasPricesOnChain: () => Promise + public fetchMedianGasPriceOffChain: () => Promise + public askOracle: (oracle: OffChainOracle) => Promise + public fetchGasPricesOffChain: (shouldGetMedian?: boolean) => Promise + public gasPrices: (fallbackGasPrices?: GasPrice, shouldGetMedian?: boolean) => Promise +} diff --git a/src/services/rpcFetcher/fetcher.ts b/src/services/rpcFetcher/fetcher.ts new file mode 100644 index 0000000..7152dc3 --- /dev/null +++ b/src/services/rpcFetcher/fetcher.ts @@ -0,0 +1,23 @@ +import axios, { AxiosResponse } from 'axios' +import { MakeRpcCallInput } from './types' + +export class RpcFetcher { + private readonly rpc: string + private readonly timeout: number + + constructor(rpc: string, timeout: number) { + this.rpc = rpc + this.timeout = timeout + } + + public async makeRpcCall({ rpc, timeout, method, params }: MakeRpcCallInput): Promise> { + const body = { + method, + id: 1337, + jsonrpc: '2.0', + params: params, + } + + return await axios.post(rpc || this.rpc, body, { timeout: timeout || this.timeout }) + } +} diff --git a/src/services/rpcFetcher/index.ts b/src/services/rpcFetcher/index.ts new file mode 100644 index 0000000..a2765b8 --- /dev/null +++ b/src/services/rpcFetcher/index.ts @@ -0,0 +1,2 @@ +export * from './fetcher' +export * from './types' diff --git a/src/services/rpcFetcher/types.ts b/src/services/rpcFetcher/types.ts new file mode 100644 index 0000000..dfaaa77 --- /dev/null +++ b/src/services/rpcFetcher/types.ts @@ -0,0 +1,7 @@ +export type Params = (string | number | number[] | Record | boolean)[] +export type MakeRpcCallInput = { + rpc?: string + method: string + timeout?: number + params: Params +} diff --git a/src/tests/complex.test.ts b/src/tests/complex.test.ts new file mode 100644 index 0000000..5f457ed --- /dev/null +++ b/src/tests/complex.test.ts @@ -0,0 +1,134 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import chai from 'chai' +import BigNumber from 'bignumber.js' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import mockery from 'mockery' +import { before, describe } from 'mocha' + +import { GWEI_PRECISION } from '@/constants' +import { GasPriceOracle, GasPrice } from '@/services' + +chai.use(require('chai-as-promised')) +chai.should() + +let oracle = new GasPriceOracle() + +before('before', async () => { + const gasPrice = await oracle.legacy.gasPrices() + console.log('legacy gasPrice - ', { gasPrice }) +}) + +before('before', function () { + const axiosMock = { + get: () => { + throw new Error('axios GET method is mocked for tests') + }, + post: () => { + throw new Error('axios POST method is mocked for tests') + }, + } + mockery.registerMock('axios', axiosMock) +}) + +beforeEach('beforeEach', function () { + oracle = new GasPriceOracle() +}) + +const INJECTED_CHAIN_ID = 5 +const INJECTED_RPC_URL = 'https://rpc.goerli.mudit.blog/' + +describe('complex test', function () { + describe('fetching data', function () { + describe('should work with unexpected chainId', function () { + // it('legacy', async function () { + // const newOracle = new GasPriceOracle({ chainId: ChainId.XDAI }) + // + // for (let i = 0; i < 100; i++) { + // const res = await newOracle.eip1559.estimateFees() + // await new Promise((r) => + // setTimeout(() => { + // r(console.log(`res - ${i}`, res)) + // }, 3000), + // ) + // } + // }) + + it('legacy', async function () { + const newOracle = new GasPriceOracle({ timeout: 1337, chainId: INJECTED_CHAIN_ID, defaultRpc: INJECTED_RPC_URL }) + + const goerliGas = (await newOracle.gasPrices({ isLegacy: true })) as unknown as GasPrice + if ('instant' in goerliGas) { + goerliGas.instant.should.be.a('number') + goerliGas.fast.should.be.a('number') + goerliGas.standard.should.be.a('number') + goerliGas.low.should.be.a('number') + } + + newOracle.legacy.configuration.defaultRpc.should.be.equal(INJECTED_RPC_URL) + newOracle.legacy.configuration.chainId.should.be.equal(INJECTED_CHAIN_ID) + }) + it('eip-1559', async function () { + const newOracle = new GasPriceOracle({ timeout: 1337, chainId: INJECTED_CHAIN_ID, defaultRpc: INJECTED_RPC_URL }) + + const goerliEstimated = await newOracle.eip1559.estimateFees() + if (goerliEstimated.baseFee) { + goerliEstimated.baseFee.should.be.a('number') + + goerliEstimated.maxFeePerGas.should.be.at.least(goerliEstimated.baseFee) + const estimatedMaxFee = new BigNumber(goerliEstimated.baseFee) + .plus(goerliEstimated.maxPriorityFeePerGas) + .decimalPlaces(GWEI_PRECISION) + .toNumber() + goerliEstimated.maxFeePerGas.should.be.at.equal(estimatedMaxFee) + } + + goerliEstimated.maxFeePerGas.should.be.a('number') + goerliEstimated.maxPriorityFeePerGas.should.be.a('number') + + newOracle.legacy.configuration.defaultRpc.should.be.equal(INJECTED_RPC_URL) + newOracle.legacy.configuration.chainId.should.be.equal(INJECTED_CHAIN_ID) + }) + it('without selected strategy', async function () { + const newOracle = new GasPriceOracle({ timeout: 1337, chainId: INJECTED_CHAIN_ID, defaultRpc: INJECTED_RPC_URL }) + + const gasPrice = await newOracle.gasPrices({}) + + if ('baseFee' in gasPrice && gasPrice.baseFee) { + gasPrice.baseFee.should.be.a('number') + + gasPrice.maxFeePerGas.should.be.at.least(gasPrice.baseFee) + const estimatedMaxFee = new BigNumber(gasPrice.baseFee) + .plus(gasPrice.maxPriorityFeePerGas) + .decimalPlaces(GWEI_PRECISION) + .toNumber() + gasPrice.maxFeePerGas.should.be.at.equal(estimatedMaxFee) + } + + if ('maxFeePerGas' in gasPrice) { + gasPrice.maxFeePerGas.should.be.a('number') + gasPrice.maxPriorityFeePerGas.should.be.a('number') + } + + if ('instant' in gasPrice) { + gasPrice.instant.should.be.a('number') + gasPrice.fast.should.be.a('number') + gasPrice.standard.should.be.a('number') + gasPrice.low.should.be.a('number') + } + + newOracle.legacy.configuration.defaultRpc.should.be.equal(INJECTED_RPC_URL) + newOracle.legacy.configuration.chainId.should.be.equal(INJECTED_CHAIN_ID) + }) + }) + }) +}) + +after('after', function () { + after(function () { + mockery.disable() + mockery.deregisterMock('node-fetch') + }) +}) diff --git a/src/tests/eip1559.test.ts b/src/tests/eip1559.test.ts new file mode 100644 index 0000000..5a21094 --- /dev/null +++ b/src/tests/eip1559.test.ts @@ -0,0 +1,134 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import chai from 'chai' +import BigNumber from 'bignumber.js' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import chaiAsPromised from 'chai-as-promised' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import mockery from 'mockery' +import { before, describe } from 'mocha' + +import { ChainId, NETWORKS } from '@/config' +import { GWEI_PRECISION } from '@/constants' + +import { GasPriceOracle } from '@/services/gas-price-oracle' +import { EstimatedGasPrice } from '@/services/gas-estimation' +import { FALLBACK_ESTIMATE } from '@/services/gas-estimation/constants' + +chai.use(chaiAsPromised) +chai.should() + +let oracle = new GasPriceOracle() + +before('before', async () => { + const gasPrice = await oracle.eip1559.estimateFees() + console.log('eip estimation -', { gasPrice }) +}) + +// +beforeEach('beforeEach', function () { + oracle = new GasPriceOracle() +}) + +const INJECTED_RPC_URL = 'https://ethereum-rpc.trustwalletapp.com' +describe('eip-1559 gasOracle', function () { + describe('eip constructor', function () { + it('should set default values', function () { + oracle.eip1559.configuration.blocksCount.should.be.equal(NETWORKS[oracle.eip1559.configuration.chainId].blocksCount) + oracle.eip1559.configuration.percentile.should.be.equal(NETWORKS[oracle.eip1559.configuration.chainId].percentile) + }) + + it('should set passed values', function () { + const newHistoryBlocks = 15 + const newHistoryPercentile = 10 + + const newOracle = new GasPriceOracle({ + blocksCount: newHistoryBlocks, + percentile: newHistoryPercentile, + }) + + newOracle.eip1559.configuration.blocksCount.should.be.equal(newHistoryBlocks) + newOracle.eip1559.configuration.percentile.should.be.equal(newHistoryPercentile) + }) + }) + + const chains = Object.keys(NETWORKS).map((id) => Number(id)) + + chains.forEach((chainId) => { + let eipOracle = new GasPriceOracle({ chainId }) + + describe(`estimateGas ${chainId}`, function () { + it('should return error if not eip-1559 not supported', async function () { + if (chainId === ChainId.OPTIMISM || chainId === ChainId.ARBITRUM || chainId === ChainId.BSC) { + await eipOracle.eip1559 + .estimateFees() + .should.be.rejectedWith('An error occurred while fetching current base fee, falling back') + } + }) + + if (chainId === ChainId.OPTIMISM || chainId === ChainId.ARBITRUM || chainId === ChainId.BSC) { + return + } + + it('should work', async function () { + const estimateGas: EstimatedGasPrice = await eipOracle.eip1559.estimateFees() + + console.log(`estimateGas ${chainId}`, estimateGas) + if (estimateGas.baseFee) { + estimateGas.baseFee.should.be.a('number') + estimateGas.maxFeePerGas.should.be.a('number') + estimateGas.maxPriorityFeePerGas.should.be.a('number') + + estimateGas.maxFeePerGas.should.be.at.least(estimateGas.baseFee) + const estimatedMaxFee = new BigNumber(estimateGas.baseFee) + .plus(estimateGas.maxPriorityFeePerGas) + .decimalPlaces(GWEI_PRECISION) + .toNumber() + estimateGas.maxFeePerGas.should.be.at.equal(estimatedMaxFee) + } + }) + + it('should work with crashed rpc (return default data)', async function () { + eipOracle = new GasPriceOracle({ defaultRpc: 'wrongRpcUrl', chainId }) + const estimateGas: EstimatedGasPrice = await eipOracle.eip1559.estimateFees(FALLBACK_ESTIMATE) + + if (estimateGas.baseFee) { + estimateGas.baseFee.should.be.a('number') + estimateGas.maxFeePerGas.should.be.a('number') + estimateGas.maxPriorityFeePerGas.should.be.a('number') + + estimateGas.baseFee.should.be.at.equal(FALLBACK_ESTIMATE.baseFee) + estimateGas.maxFeePerGas.should.be.at.equal(FALLBACK_ESTIMATE.maxFeePerGas) + estimateGas.maxPriorityFeePerGas.should.be.at.equal(FALLBACK_ESTIMATE.maxPriorityFeePerGas) + } + }) + + it('should work with custom rpc', async function () { + eipOracle = new GasPriceOracle({ defaultRpc: INJECTED_RPC_URL, chainId }) + const estimateGas: EstimatedGasPrice = await eipOracle.eip1559.estimateFees(FALLBACK_ESTIMATE) + + if (estimateGas.baseFee) { + estimateGas.baseFee.should.be.a('number') + estimateGas.maxFeePerGas.should.be.a('number') + estimateGas.maxPriorityFeePerGas.should.be.a('number') + + const estimatedMaxFee = new BigNumber(estimateGas.baseFee) + .plus(estimateGas.maxPriorityFeePerGas) + .decimalPlaces(GWEI_PRECISION) + .toNumber() + estimateGas.maxFeePerGas.should.be.at.least(estimateGas.baseFee) + estimateGas.maxFeePerGas.should.be.at.equal(estimatedMaxFee) + } + }) + }) + }) +}) + +after('after', function () { + after(function () { + mockery.disable() + mockery.deregisterMock('node-fetch') + }) +}) diff --git a/src/tests/legacy.test.ts b/src/tests/legacy.test.ts new file mode 100644 index 0000000..da4eebe --- /dev/null +++ b/src/tests/legacy.test.ts @@ -0,0 +1,358 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import chai from 'chai' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import mockery from 'mockery' +import BigNumber from 'bignumber.js' +import { before, describe } from 'mocha' + +import { ChainId, NETWORKS } from '@/config' +import { DEFAULT_TIMEOUT } from '@/constants' +import { GasPriceOracle } from '@/services/gas-price-oracle' +import { GasPrice, LegacyGasPriceOracle, OffChainOracle } from '@/services/legacy-gas-price' + +chai.use(require('chai-as-promised')) +chai.should() + +let oracle = new GasPriceOracle() +let { onChainOracles, offChainOracles } = oracle.legacy + +before('before', async () => { + const gasPrice = await oracle.legacy.gasPrices() + console.log('legacy gasPrice - ', { gasPrice }) +}) + +before('before', function () { + const axiosMock = { + get: () => { + throw new Error('axios GET method is mocked for tests') + }, + post: () => { + throw new Error('axios POST method is mocked for tests') + }, + } + mockery.registerMock('axios', axiosMock) +}) + +beforeEach('beforeEach', function () { + oracle = new GasPriceOracle() + ;({ onChainOracles, offChainOracles } = oracle.legacy) +}) + +const INJECTED_RPC_URL = 'https://ethereum-rpc.trustwalletapp.com' + +describe('legacy gasOracle', function () { + describe('legacy constructor', function () { + it('should set default values', function () { + oracle.legacy.configuration.defaultRpc.should.be.equal(NETWORKS[ChainId.MAINNET].rpcUrl) + oracle.legacy.configuration.timeout.should.be.equal(DEFAULT_TIMEOUT) + }) + + it('should set passed values', function () { + const newOracle = new GasPriceOracle({ timeout: 1337 }) + + newOracle.legacy.configuration.defaultRpc.should.be.equal(NETWORKS[ChainId.MAINNET].rpcUrl) + newOracle.legacy.configuration.timeout.should.be.equal(1337) + }) + }) + + describe('fetchGasPricesOffChain', function () { + it('should work', async function () { + const gas: GasPrice = await oracle.legacy.fetchGasPricesOffChain(true) + + gas.instant.should.be.a('number') + gas.fast.should.be.a('number') + gas.standard.should.be.a('number') + gas.low.should.be.a('number') + + gas.instant.should.be.at.least(gas.fast) + gas.fast.should.be.at.least(gas.standard) + gas.standard.should.be.at.least(gas.low) + gas.low.should.not.be.equal(0) + }) + + it('should throw if all offchain oracles are down', async function () { + mockery.enable({ useCleanCache: true, warnOnUnregistered: false }) + const { GasPriceOracle } = require('../index') + oracle = new GasPriceOracle() + await oracle.legacy.fetchGasPricesOffChain(true).should.be.rejectedWith('All oracles are down. Probably a network error.') + mockery.disable() + }) + }) + + describe('fetchGasPricesOnChain', function () { + it('should work', async function () { + const gas: number = await oracle.legacy.fetchGasPricesOnChain() + gas.should.be.a('number') + gas.should.be.above(1) + gas.should.not.be.equal(0) + }) + + it('should work with custom rpc', async function () { + const rpc = INJECTED_RPC_URL + oracle = new GasPriceOracle({ defaultRpc: rpc }) + oracle.legacy.configuration.defaultRpc.should.be.equal(rpc) + const gas: number = await oracle.legacy.fetchGasPricesOnChain() + + gas.should.be.a('number') + + gas.should.be.above(1) + gas.should.not.be.equal(0) + }) + + it('should remove oracle', async function () { + await oracle.legacy.fetchGasPricesOnChain() + oracle.legacy.removeOnChainOracle('chainlink') + await oracle.legacy.fetchGasPricesOnChain().should.be.rejectedWith('All oracles are down. Probably a network error.') + }) + + it('should add oracle', async function () { + const toAdd = onChainOracles.chainlink + await oracle.legacy.fetchGasPricesOnChain() + oracle.legacy.removeOnChainOracle('chainlink') + + await oracle.legacy.fetchGasPricesOnChain().should.be.rejectedWith('All oracles are down. Probably a network error.') + + oracle.legacy.addOnChainOracle(toAdd) + const gas: number = await oracle.legacy.fetchGasPricesOnChain() + + gas.should.be.a('number') + gas.should.not.be.equal(0) + }) + + it('should throw if all onchain oracles are down', async function () { + mockery.enable({ useCleanCache: true, warnOnUnregistered: false }) + const { GasPriceOracle } = require('../index') + + oracle = new GasPriceOracle() + await oracle.legacy.fetchGasPricesOnChain().should.be.rejectedWith('All oracles are down. Probably a network error.') + mockery.disable() + }) + }) + + describe('fetchGasPriceFromRpc', function () { + it('should work', async function () { + const gas: number = await oracle.legacy.fetchGasPriceFromRpc() + gas.should.be.a('number') + gas.should.be.above(1) + gas.should.not.be.equal(0) + }) + + it('should work with custom rpc', async function () { + const rpc = INJECTED_RPC_URL + const oracle = new GasPriceOracle({ defaultRpc: rpc }) + oracle.legacy.configuration.defaultRpc.should.be.equal(rpc) + const gas: number = await oracle.legacy.fetchGasPriceFromRpc() + + gas.should.be.a('number') + + gas.should.be.above(1) + gas.should.not.be.equal(0) + }) + + it('should throw if default rpc is down', async function () { + mockery.enable({ useCleanCache: true, warnOnUnregistered: false }) + const { GasPriceOracle } = require('../index') + + oracle = new GasPriceOracle() + await oracle.legacy.fetchGasPriceFromRpc().should.be.rejectedWith('Default RPC is down. Probably a network error.') + mockery.disable() + }) + }) + + describe('legacy gasPrice', function () { + it('should work', async function () { + const gas = (await oracle.gasPrices({ isLegacy: true })) as unknown as GasPrice + + gas.instant.should.be.a('number') + gas.fast.should.be.a('number') + gas.standard.should.be.a('number') + gas.low.should.be.a('number') + + gas.instant.should.be.at.least(gas.fast) + gas.fast.should.be.at.least(gas.standard) + gas.standard.should.be.at.least(gas.low) + gas.low.should.not.be.equal(0) + }) + + it('should fallback', async function () { + mockery.enable({ useCleanCache: true, warnOnUnregistered: false }) + const { GasPriceOracle } = require('../index') + + oracle = new GasPriceOracle() + + const gas = (await oracle.gasPrices({ isLegacy: true })) as unknown as GasPrice + + const shouldBe = LegacyGasPriceOracle.getMultipliedPrices(NETWORKS[ChainId.MAINNET].defaultGasPrice) + + gas.instant.should.be.equal(shouldBe.instant) + gas.fast.should.be.equal(shouldBe.fast) + gas.standard.should.be.equal(shouldBe.standard) + gas.low.should.be.equal(shouldBe.low) + + mockery.disable() + }) + + it('should fallback to set values', async function () { + mockery.enable({ useCleanCache: true, warnOnUnregistered: false }) + const { GasPriceOracle } = require('../index') + oracle = new GasPriceOracle() + + const fallbackGasPrices = { + gasPrices: { + instant: 50, + fast: 21, + standard: 10, + low: 3, + }, + } + const gas = (await oracle.gasPrices({ isLegacy: true, fallbackGasPrices })) as unknown as GasPrice + + gas.instant.should.be.equal(fallbackGasPrices.gasPrices.instant) + gas.fast.should.be.equal(fallbackGasPrices.gasPrices.fast) + gas.standard.should.be.equal(fallbackGasPrices.gasPrices.standard) + gas.low.should.be.equal(fallbackGasPrices.gasPrices.low) + + mockery.disable() + }) + }) + + describe('median', function () { + it('should work', function () { + const gas1 = { instant: 100, fast: 100, standard: 100, low: 100 } + const gas2 = { instant: 90, fast: 90, standard: 90, low: 90 } + const gas3 = { instant: 70, fast: 70, standard: 70, low: 70 } + const gas4 = { instant: 110.1, fast: 110.1, standard: 110.1, low: 110.1 } + + let gas: GasPrice = LegacyGasPriceOracle.getMedianGasPrice([gas1, gas2, gas3]) + + gas.instant.should.be.a('number') + gas.fast.should.be.a('number') + gas.standard.should.be.a('number') + gas.low.should.be.a('number') + + gas.instant.should.be.eq(90) + gas.fast.should.be.eq(90) + gas.standard.should.be.eq(90) + gas.low.should.be.eq(90) + + gas = LegacyGasPriceOracle.getMedianGasPrice([gas1, gas2, gas3, gas4]) + + gas.instant.should.be.a('number') + gas.fast.should.be.a('number') + gas.standard.should.be.a('number') + gas.low.should.be.a('number') + + gas.instant.should.be.eq(95) + gas.fast.should.be.eq(95) + gas.standard.should.be.eq(95) + gas.low.should.be.eq(95) + }) + }) + + describe('fetchMedianGasPriceOffChain', function () { + it('should work', async function () { + const gas: GasPrice = await oracle.legacy.fetchMedianGasPriceOffChain() + + gas.instant.should.be.a('number') + gas.fast.should.be.a('number') + gas.standard.should.be.a('number') + gas.low.should.be.a('number') + + gas.instant.should.be.at.least(gas.fast) + gas.fast.should.be.at.least(gas.standard) + gas.standard.should.be.at.least(gas.low) + gas.low.should.not.be.equal(0) + }) + }) + + describe('normalize result values', function () { + const wrongDecimalsGas = { + gasPrices: { + instant: 1.1, + fast: 2.12345678901, + standard: 3.12345678901, + low: 3.12345679, + }, + } + + const checkDecimals = (gas: GasPrice) => { + const gasPrices: number[] = Object.values(gas) + + for (const gas of gasPrices) { + new BigNumber(gas).dp().should.be.at.most(9) + } + } + + it('default fallback should be normalized', function () { + mockery.enable({ useCleanCache: true, warnOnUnregistered: false }) + + oracle = new GasPriceOracle({ fallbackGasPrices: wrongDecimalsGas }) + + checkDecimals(oracle.legacy.configuration.fallbackGasPrices) + + mockery.disable() + }) + + it('fallback should be normalized', async function () { + mockery.enable({ useCleanCache: true, warnOnUnregistered: false }) + const { GasPriceOracle } = require('../index') + + oracle = new GasPriceOracle() + + const gas = await oracle.legacy.gasPrices(wrongDecimalsGas.gasPrices) + + checkDecimals(gas) + mockery.disable() + }) + + it('rpc fallback should be normalized', async function () { + oracle = new GasPriceOracle({ chainId: 42161, defaultRpc: 'https://arb1.arbitrum.io/rpc' }) + + const gas = await oracle.legacy.gasPrices() + + checkDecimals(gas) + }) + }) + + describe('askOracle', function () { + const chains = Object.keys(NETWORKS).map((id) => Number(id)) + + chains.forEach((chainId) => { + describe(`all ${ChainId[chainId]} oracles should answer`, function () { + oracle = new GasPriceOracle({ chainId }) + ;({ offChainOracles } = oracle.legacy) + + for (const o of Object.values(offChainOracles) as OffChainOracle[]) { + it(`check ${o.name}`, async function () { + try { + const gas: GasPrice = await oracle.legacy.askOracle(o) + + gas.instant.should.be.a('number') + gas.fast.should.be.a('number') + gas.standard.should.be.a('number') + gas.low.should.be.a('number') + + gas.instant.should.be.at.least(gas.fast) + gas.fast.should.be.at.least(gas.standard) + gas.standard.should.be.at.least(gas.low) + gas.low.should.not.be.equal(0) + } catch (e) { + console.error(`Failed to get data from ${o.name} oracle`) + throw new Error(e) + } + }) + } + }) + }) + }) +}) + +after('after', function () { + after(function () { + mockery.disable() + mockery.deregisterMock('node-fetch') + }) +}) diff --git a/src/types.ts b/src/types.ts index 558428e..f8a290f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,46 +1,40 @@ -export type OffChainOracle = { - name: string; - url: string; - instantPropertyName: string; - fastPropertyName: string; - standardPropertyName: string; - lowPropertyName: string; - denominator: number; - additionalDataProperty: string | null; -}; +import { AllOracles } from './services/legacy-gas-price' -export type OffChainOracles = { [key: string]: OffChainOracle }; +export interface Block { + baseFeePerGas: string + difficulty: string + extraData: string + gasLimit: string + gasUsed: string + hash: string + miner: string + mixHash: string + nonce: string + number: string + parentHash: string + receiptsRoot: string + sha3Uncles: string + size: string + stateRoot: string + timestamp: string + totalDifficulty: string + transactions: unknown[] + transactionsRoot: string + uncles: unknown[] +} -export type OnChainOracle = { - name: string; - rpc?: string; - contract: string; - callData: string; - denominator: string; -}; +export interface FeeHistory { + baseFeePerGas: string[] + gasUsedRatio: number[] + reward?: string[][] + oldestBlock: string +} -export type OnChainOracles = { [key: string]: OnChainOracle }; - -export type AllOracles = { - offChainOracles: OffChainOracles; - onChainOracles: OnChainOracles; -}; - -export type GasPrice = { - [key in GasPriceKey]: number; -}; - -export type GasPriceKey = 'instant' | 'fast' | 'standard' | 'low'; - -export type Options = { - chainId?: number; - defaultRpc?: string; - timeout?: number; - defaultFallbackGasPrices?: GasPrice; -}; - -export type Config = Required; - -export type NetworkConfig = { - [key in number]: AllOracles; -}; +export type NetworksConfig = { + oracles: AllOracles + rpcUrl: string + defaultGasPrice: number + maxGasPrice: number + blocksCount: number + percentile: number +} diff --git a/src/utils/crypto.ts b/src/utils/crypto.ts new file mode 100644 index 0000000..da94c4c --- /dev/null +++ b/src/utils/crypto.ts @@ -0,0 +1,20 @@ +import BigNumber from 'bignumber.js' +import { GWEI, GWEI_PRECISION } from '@/constants' + +const toGwei = (amount: number | string | BigNumber): BigNumber => { + return new BigNumber(amount).multipliedBy(GWEI).decimalPlaces(GWEI_PRECISION) +} + +const fromWeiToGwei = (amount: number | string | BigNumber): BigNumber => { + return new BigNumber(amount).dividedBy(GWEI).decimalPlaces(GWEI_PRECISION) +} + +const fromNumberToHex = (amount: number | string | BigNumber): string => { + return `0x${new BigNumber(amount).toString(16)}` +} + +const fromGweiToWeiHex = (value: number): string => { + return fromNumberToHex(new BigNumber(value).multipliedBy(GWEI).decimalPlaces(0)) +} + +export { toGwei, fromWeiToGwei, fromGweiToWeiHex, fromNumberToHex } diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..7091bed --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from './math' +export * from './crypto' diff --git a/src/utils/math.ts b/src/utils/math.ts new file mode 100644 index 0000000..488912c --- /dev/null +++ b/src/utils/math.ts @@ -0,0 +1,45 @@ +import BigNumber from 'bignumber.js' + +import { BG_ZERO, PERCENT_MULTIPLIER } from '@/constants' + +import { toGwei } from './crypto' + +type FindMaxRes = { + highest: BigNumber + index: number +} + +const findMax = (values: BigNumber[]): FindMaxRes => { + return values.reduce( + (acc, curr, index) => { + const isGreaterThanAcc = curr.isGreaterThan(acc.highest) + if (isGreaterThanAcc) { + acc.highest = curr + acc.index = index + } + return acc + }, + { + highest: BG_ZERO, + index: 0, + }, + ) +} + +const getMedian = (arr: T[]): number => { + return Math.floor(arr.length / 2) +} + +const round = (value: number | string | BigNumber): BigNumber => { + return new BigNumber(value).decimalPlaces(0, 2) +} + +const roundGwei = (value: number | string | BigNumber): BigNumber => { + return toGwei(value).decimalPlaces(0, 2) +} + +const bumpOnPercent = (value: number, bumpPercent: number): number => { + return value + (value * bumpPercent) / PERCENT_MULTIPLIER +} + +export { findMax, getMedian, round, roundGwei, bumpOnPercent } diff --git a/tests/index.test.ts b/tests/index.test.ts deleted file mode 100644 index a6b2d77..0000000 --- a/tests/index.test.ts +++ /dev/null @@ -1,333 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -/* eslint-disable @typescript-eslint/no-var-requires */ -import chai from 'chai'; -import mockery from 'mockery'; -import BigNumber from 'bignumber.js'; - -import { ChainId, NETWORKS } from '../src/config'; -import { GasPriceOracle } from '../src/index'; - -import { GasPrice, OffChainOracle } from '../src/types'; - -chai.use(require('chai-as-promised')); -chai.should(); - -let oracle = new GasPriceOracle(); -let { onChainOracles, offChainOracles } = oracle; - -before('before', function () { - const axiosMock = { - get: () => { - throw new Error('axios GET method is mocked for tests'); - }, - post: () => { - throw new Error('axios POST method is mocked for tests'); - }, - }; - mockery.registerMock('axios', axiosMock); -}); - -beforeEach('beforeEach', function () { - oracle = new GasPriceOracle(); - ({ onChainOracles, offChainOracles } = oracle); -}); - -describe('constructor', function () { - it('should set default values', async function () { - oracle.configuration.defaultRpc.should.be.equal('https://api.mycryptoapi.com/eth'); - oracle.configuration.timeout.should.be.equal(10000); - }); - - it('should set passed values', async function () { - const newOracle = new GasPriceOracle({ timeout: 1337 }); - newOracle.configuration.defaultRpc.should.be.equal('https://api.mycryptoapi.com/eth'); - newOracle.configuration.timeout.should.be.equal(1337); - }); -}); - -describe('fetchGasPricesOffChain', function () { - it('should work', async function () { - const gas: GasPrice = await oracle.fetchGasPricesOffChain(); - - gas.instant.should.be.a('number'); - gas.fast.should.be.a('number'); - gas.standard.should.be.a('number'); - gas.low.should.be.a('number'); - - gas.instant.should.be.at.least(gas.fast); // greater than or equal to the given number. - gas.fast.should.be.at.least(gas.standard); - gas.standard.should.be.at.least(gas.low); - gas.low.should.not.be.equal(0); - }); - - it('should throw if all offchain oracles are down', async function () { - mockery.enable({ useCleanCache: true, warnOnUnregistered: false }); - const { GasPriceOracle } = require('../src/index'); - oracle = new GasPriceOracle(); - await oracle - .fetchGasPricesOffChain() - .should.be.rejectedWith('All oracles are down. Probably a network error.'); - mockery.disable(); - }); -}); - -describe('fetchGasPricesOnChain', function () { - it('should work', async function () { - const gas: number = await oracle.fetchGasPricesOnChain(); - gas.should.be.a('number'); - gas.should.be.above(1); - gas.should.not.be.equal(0); - }); - - it('should work with custom rpc', async function () { - const rpc = 'https://ethereum-rpc.trustwalletapp.com'; - const oracle = new GasPriceOracle({ defaultRpc: rpc }); - oracle.configuration.defaultRpc.should.be.equal(rpc); - const gas: number = await oracle.fetchGasPricesOnChain(); - - gas.should.be.a('number'); - - gas.should.be.above(1); - gas.should.not.be.equal(0); - }); - - it('should remove oracle', async function () { - await oracle.fetchGasPricesOnChain(); - oracle.removeOnChainOracle('chainlink'); - await oracle - .fetchGasPricesOnChain() - .should.be.rejectedWith('All oracles are down. Probably a network error.'); - }); - - it('should add oracle', async function () { - const { chainlink } = onChainOracles; - await oracle.fetchGasPricesOnChain(); - oracle.removeOnChainOracle('chainlink'); - await oracle - .fetchGasPricesOnChain() - .should.be.rejectedWith('All oracles are down. Probably a network error.'); - oracle.addOnChainOracle(chainlink); - const gas: number = await oracle.fetchGasPricesOnChain(); - - gas.should.be.a('number'); - gas.should.not.be.equal(0); - }); - - it('should throw if all onchain oracles are down', async function () { - mockery.enable({ useCleanCache: true, warnOnUnregistered: false }); - const { GasPriceOracle } = require('../src/index'); - oracle = new GasPriceOracle(); - await oracle - .fetchGasPricesOnChain() - .should.be.rejectedWith('All oracles are down. Probably a network error.'); - mockery.disable(); - }); -}); - -describe('fetchGasPriceFromRpc', function () { - it('should work', async function () { - const gas: number = await oracle.fetchGasPriceFromRpc(); - gas.should.be.a('number'); - gas.should.be.above(1); - gas.should.not.be.equal(0); - }); - - it('should work with custom rpc', async function () { - const rpc = 'https://ethereum-rpc.trustwalletapp.com'; - const oracle = new GasPriceOracle({ defaultRpc: rpc }); - oracle.configuration.defaultRpc.should.be.equal(rpc); - const gas: number = await oracle.fetchGasPriceFromRpc(); - - gas.should.be.a('number'); - - gas.should.be.above(1); - gas.should.not.be.equal(0); - }); - - it('should throw if default rpc is down', async function () { - mockery.enable({ useCleanCache: true, warnOnUnregistered: false }); - const { GasPriceOracle } = require('../src/index'); - oracle = new GasPriceOracle(); - await oracle - .fetchGasPriceFromRpc() - .should.be.rejectedWith('Default RPC is down. Probably a network error.'); - mockery.disable(); - }); -}); - -describe('gasPrice', function () { - it('should work', async function () { - const gas: GasPrice = await oracle.gasPrices(); - - gas.instant.should.be.a('number'); - gas.fast.should.be.a('number'); - gas.standard.should.be.a('number'); - gas.low.should.be.a('number'); - - gas.instant.should.be.at.least(gas.fast); - gas.fast.should.be.at.least(gas.standard); - gas.standard.should.be.at.least(gas.low); - gas.low.should.not.be.equal(0); - }); - it('should fallback', async function () { - mockery.enable({ useCleanCache: true, warnOnUnregistered: false }); - const { GasPriceOracle } = require('../src/index'); - oracle = new GasPriceOracle(); - const gas: GasPrice = await oracle.gasPrices(); - - gas.instant.should.be.equal(28.6); - gas.fast.should.be.equal(22); - gas.standard.should.be.equal(18.7); - gas.low.should.be.equal(11); - mockery.disable(); - }); - - it('should fallback to set values', async function () { - mockery.enable({ useCleanCache: true, warnOnUnregistered: false }); - const { GasPriceOracle } = require('../src/index'); - oracle = new GasPriceOracle(); - const gas: GasPrice = await oracle.gasPrices({ instant: 50, fast: 21, standard: 10, low: 3 }); - - gas.instant.should.be.equal(50); - gas.fast.should.be.equal(21); - gas.standard.should.be.equal(10); - gas.low.should.be.equal(3); - mockery.disable(); - }); -}); - -describe('median', function () { - it('should work', async function () { - const gas1 = { instant: 100, fast: 100, standard: 100, low: 100 }; - const gas2 = { instant: 90, fast: 90, standard: 90, low: 90 }; - const gas3 = { instant: 70, fast: 70, standard: 70, low: 70 }; - const gas4 = { instant: 110.1, fast: 110.1, standard: 110.1, low: 110.1 }; - let gas: GasPrice = await oracle.median([gas1, gas2, gas3]); - gas.instant.should.be.a('number'); - gas.fast.should.be.a('number'); - gas.standard.should.be.a('number'); - gas.low.should.be.a('number'); - - gas.instant.should.be.eq(90); - gas.fast.should.be.eq(90); - gas.standard.should.be.eq(90); - gas.low.should.be.eq(90); - - gas = await oracle.median([gas1, gas2, gas3, gas4]); - gas.instant.should.be.a('number'); - gas.fast.should.be.a('number'); - gas.standard.should.be.a('number'); - gas.low.should.be.a('number'); - - gas.instant.should.be.eq(95); - gas.fast.should.be.eq(95); - gas.standard.should.be.eq(95); - gas.low.should.be.eq(95); - }); -}); - -describe('fetchMedianGasPriceOffChain', function () { - it('should work', async function () { - const gas: GasPrice = await oracle.fetchMedianGasPriceOffChain(); - gas.instant.should.be.a('number'); - gas.fast.should.be.a('number'); - gas.standard.should.be.a('number'); - gas.low.should.be.a('number'); - - gas.instant.should.be.at.least(gas.fast); // greater than or equal to the given number. - gas.fast.should.be.at.least(gas.standard); - gas.standard.should.be.at.least(gas.low); - gas.low.should.not.be.equal(0); - }); -}); - -describe('normalize result values', function () { - const wrongDecimalsGas = { - instant: 1.1, - fast: 2.12345678901, - standard: 3.12345678901, - low: 3.1234567890123456789, - }; - - const checkDecimals = (gas: GasPrice) => { - const gasPrices: number[] = Object.values(gas); - - for (const gas of gasPrices) { - new BigNumber(gas).dp().should.be.at.most(9); - } - }; - - it('default fallback should be normalized', function () { - mockery.enable({ useCleanCache: true, warnOnUnregistered: false }); - - const { GasPriceOracle } = require('../src/index'); - oracle = new GasPriceOracle({ - defaultFallbackGasPrices: wrongDecimalsGas, - }); - const { configuration } = oracle; - - checkDecimals(configuration.defaultFallbackGasPrices); - - mockery.disable(); - }); - - it('fallback should be normalized', async function () { - mockery.enable({ useCleanCache: true, warnOnUnregistered: false }); - - const { GasPriceOracle } = require('../src/index'); - oracle = new GasPriceOracle(); - - const gas = await oracle.gasPrices(wrongDecimalsGas); - - checkDecimals(gas); - mockery.disable(); - }); - - it('rpc fallback should be normalized', async function () { - const { GasPriceOracle } = require('../src/index'); - oracle = new GasPriceOracle({ chainId: 42161, defaultRpc: 'https://arb1.arbitrum.io/rpc' }); - - const gas = await oracle.gasPrices(); - - checkDecimals(gas); - }); -}); - -describe('askOracle', function () { - const chains = Object.keys(NETWORKS).map(id => Number(id)); - - chains.forEach(chainId => { - describe(`all ${ChainId[chainId]} oracles should answer`, function () { - oracle = new GasPriceOracle({ chainId }); - ({ offChainOracles } = oracle); - - for (const o of Object.values(offChainOracles) as Array) { - it(`check ${o.name}`, async function () { - try { - const gas: GasPrice = await oracle.askOracle(o); - - gas.instant.should.be.a('number'); - gas.fast.should.be.a('number'); - gas.standard.should.be.a('number'); - gas.low.should.be.a('number'); - - gas.instant.should.be.at.least(gas.fast); // greater than or equal to the given number. - gas.fast.should.be.at.least(gas.standard); - gas.standard.should.be.at.least(gas.low); - gas.low.should.not.be.equal(0); - } catch (e) { - console.error(`Failed to get data from ${o.name} oracle`); - throw new Error(e); - } - }); - } - }); - }); -}); - -after('after', function () { - after(function () { - mockery.disable(); - mockery.deregisterMock('node-fetch'); - }); -}); diff --git a/tsconfig.esm.json b/tsconfig.esm.json new file mode 100644 index 0000000..f6421c6 --- /dev/null +++ b/tsconfig.esm.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "declaration": false, + "target": "es2015", + "module": "es2015", + "outDir": "lib/esm" + } +} diff --git a/tsconfig.json b/tsconfig.json index 70f89f0..7dd9c15 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,69 +1,33 @@ { "compilerOptions": { - /* Basic Options */ - "target": "es2017" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, - "lib": [ - "es2017", - "esnext.asynciterable", - "es2019", - "ES2020.Promise" - ] /* Specify library files to be included in the compilation. */, - "outDir": "./lib" /* Redirect output structure to the directory. */, - "strict": true /* Enable all strict type-checking options. */, - "strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */, - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, - "declaration": true /* Generates corresponding '.d.ts' file. */, + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "lib": ["es5", "es6", "es2021", "esnext"], + "experimentalDecorators": true, + "sourceMap": true, + "outDir": "lib", + "noImplicitAny": true, + "allowJs": true, + "declaration": true, + "skipLibCheck": true, + "esModuleInterop": true, + "checkJs": false, + "noUnusedLocals": true, + "strictNullChecks": true, + "noImplicitThis": true, + "noImplicitReturns": true, + "allowSyntheticDefaultImports": true, + "strictFunctionTypes": true, "forceConsistentCasingInFileNames": true, - // "allowJs": true, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, - "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, - "plugins": [] + "resolveJsonModule": true, + "isolatedModules": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + "types": ["@types/node"] }, - "include": ["src"], - "exclude": ["node_modules", "tests"] + "include": ["src/**/*"], + "exclude": ["node_modules", "src/tests"] } diff --git a/yarn.lock b/yarn.lock index 5a086f2..d5868c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,85 +2,98 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" -"@babel/helper-validator-identifier@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" - integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== "@babel/highlight@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" - integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" + integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" -"@eslint/eslintrc@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085" - integrity sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA== +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== dependencies: ajv "^6.12.4" debug "^4.1.1" espree "^7.3.0" - globals "^12.1.0" + globals "^13.9.0" ignore "^4.0.6" import-fresh "^3.2.1" js-yaml "^3.13.1" - lodash "^4.17.19" minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@nodelib/fs.scandir@2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" - integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== dependencies: - "@nodelib/fs.stat" "2.0.3" + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" - integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" - integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: - "@nodelib/fs.scandir" "2.1.3" + "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" "@types/chai-as-promised@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.3.tgz#779166b90fda611963a3adbfd00b339d03b747bd" - integrity sha512-FQnh1ohPXJELpKhzjuDkPLR2BZCAqed+a6xV4MI/T3XzHfd2FlarfUGUdZYgqYe8oxkYn0fchHEeHfHqdZ96sg== + version "7.1.5" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" + integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== dependencies: "@types/chai" "*" -"@types/chai@*": - version "4.2.14" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.14.tgz#44d2dd0b5de6185089375d976b4ec5caf6861193" - integrity sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ== +"@types/chai@*", "@types/chai@^4.2.11": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04" + integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ== -"@types/chai@^4.2.11": - version "4.2.13" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.13.tgz#8a3801f6655179d1803d81e94a2e4aaf317abd16" - integrity sha512-o3SGYRlOpvLFpwJA6Sl1UPOwKFEvE4FxTEB/c9XHI2whdnd4kmPVkNLL8gY4vWGBxWWDumzLbKsAhEH5SKn37Q== +"@types/json-schema@^7.0.7": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== -"@types/json-schema@^7.0.3": - version "7.0.6" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" - integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/mocha@^7.0.2": version "7.0.2" @@ -88,96 +101,96 @@ integrity sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w== "@types/mockery@^1.4.29": - version "1.4.29" - resolved "https://registry.yarnpkg.com/@types/mockery/-/mockery-1.4.29.tgz#9ba22df37f07e3780fff8531d1a38e633f9457a5" - integrity sha1-m6It838H43gP/4Ux0aOOYz+UV6U= + version "1.4.30" + resolved "https://registry.yarnpkg.com/@types/mockery/-/mockery-1.4.30.tgz#25f07fa7340371c7ee0fb9239511a34e0a19d5b7" + integrity sha512-uv53RrNdhbkV/3VmVCtfImfYCWC3GTTRn3R11Whni3EJ+gb178tkZBVNj2edLY5CMrB749dQi+SJkg87jsN8UQ== "@types/node@^14.0.5": - version "14.11.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.8.tgz#fe2012f2355e4ce08bca44aeb3abbb21cf88d33f" - integrity sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw== + version "14.18.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.21.tgz#0155ee46f6be28b2ff0342ca1a9b9fd4468bef41" + integrity sha512-x5W9s+8P4XteaxT/jKF0PSb7XEvo5VmqEWgsMlyeY4ZlLK8I6aH6g5TPPyDlLAep+GYf4kefb7HFyc7PAO3m+Q== "@typescript-eslint/eslint-plugin@^4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.4.1.tgz#b8acea0373bd2a388ac47df44652f00bf8b368f5" - integrity sha512-O+8Utz8pb4OmcA+Nfi5THQnQpHSD2sDUNw9AxNHpuYOo326HZTtG8gsfT+EAYuVrFNaLyNb2QnUNkmTRDskuRA== + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== dependencies: - "@typescript-eslint/experimental-utils" "4.4.1" - "@typescript-eslint/scope-manager" "4.4.1" - debug "^4.1.1" + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" + debug "^4.3.1" functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" + ignore "^5.1.8" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.4.1.tgz#40613b9757fa0170de3e0043254dbb077cafac0c" - integrity sha512-Nt4EVlb1mqExW9cWhpV6pd1a3DkUbX9DeyYsdoeziKOpIJ04S2KMVDO+SEidsXRH/XHDpbzXykKcMTLdTXH6cQ== +"@typescript-eslint/experimental-utils@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.4.1" - "@typescript-eslint/types" "4.4.1" - "@typescript-eslint/typescript-estree" "4.4.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" "@typescript-eslint/parser@^4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.4.1.tgz#25fde9c080611f303f2f33cedb145d2c59915b80" - integrity sha512-S0fuX5lDku28Au9REYUsV+hdJpW/rNW0gWlc4SXzF/kdrRaAVX9YCxKpziH7djeWT/HFAjLZcnY7NJD8xTeUEg== + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" + integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== dependencies: - "@typescript-eslint/scope-manager" "4.4.1" - "@typescript-eslint/types" "4.4.1" - "@typescript-eslint/typescript-estree" "4.4.1" - debug "^4.1.1" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + debug "^4.3.1" -"@typescript-eslint/scope-manager@4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.4.1.tgz#d19447e60db2ce9c425898d62fa03b2cce8ea3f9" - integrity sha512-2oD/ZqD4Gj41UdFeWZxegH3cVEEH/Z6Bhr/XvwTtGv66737XkR4C9IqEkebCuqArqBJQSj4AgNHHiN1okzD/wQ== +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== dependencies: - "@typescript-eslint/types" "4.4.1" - "@typescript-eslint/visitor-keys" "4.4.1" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" -"@typescript-eslint/types@4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.4.1.tgz#c507b35cf523bc7ba00aae5f75ee9b810cdabbc1" - integrity sha512-KNDfH2bCyax5db+KKIZT4rfA8rEk5N0EJ8P0T5AJjo5xrV26UAzaiqoJCxeaibqc0c/IvZxp7v2g3difn2Pn3w== +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== -"@typescript-eslint/typescript-estree@4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.4.1.tgz#598f6de488106c2587d47ca2462c60f6e2797cb8" - integrity sha512-wP/V7ScKzgSdtcY1a0pZYBoCxrCstLrgRQ2O9MmCUZDtmgxCO/TCqOTGRVwpP4/2hVfqMz/Vw1ZYrG8cVxvN3g== +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== dependencies: - "@typescript-eslint/types" "4.4.1" - "@typescript-eslint/visitor-keys" "4.4.1" - debug "^4.1.1" - globby "^11.0.1" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" + semver "^7.3.5" + tsutils "^3.21.0" -"@typescript-eslint/visitor-keys@4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.4.1.tgz#1769dc7a9e2d7d2cfd3318b77ed8249187aed5c3" - integrity sha512-H2JMWhLaJNeaylSnMSQFEhT/S/FsJbebQALmoJxMPMxLtlVAMy2uJP/Z543n9IizhjRayLSqoInehCeNW9rWcw== +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== dependencies: - "@typescript-eslint/types" "4.4.1" + "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" -acorn-jsx@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" - integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== +acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -187,30 +200,40 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.1: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ansi-colors@3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" @@ -219,17 +242,17 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" -anymatch@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== +anymatch@~3.1.1, anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -246,42 +269,79 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +array-includes@^3.1.4: + version "3.1.5" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" + integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array.prototype.flat@^1.2.5: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" + integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.2" + es-shim-unscopables "^1.0.0" + +array.prototype.reduce@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz#8167e80089f78bff70a99e20bd4201d4663b0a6f" + integrity sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.2" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== axios@^0.21.2: - version "0.21.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.2.tgz#21297d5084b2aeeb422f5d38e7be4fbb82239017" - integrity sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg== + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: follow-redirects "^1.14.0" balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== bignumber.js@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" - integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== + version "9.0.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673" + integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== binary-extensions@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" - integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== brace-expansion@^1.1.7: version "1.1.11" @@ -291,7 +351,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -303,10 +363,18 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer-from@^1.0.0, buffer-from@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" callsites@^3.0.0: version "3.1.0" @@ -326,15 +394,16 @@ chai-as-promised@^7.1.1: check-error "^1.0.2" chai@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" deep-eql "^3.0.1" get-func-name "^2.0.0" - pathval "^1.1.0" + loupe "^2.3.1" + pathval "^1.1.1" type-detect "^4.0.5" chalk@^2.0.0, chalk@^2.4.2: @@ -347,9 +416,9 @@ chalk@^2.0.0, chalk@^2.4.2: supports-color "^5.3.0" chalk@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" @@ -357,7 +426,7 @@ chalk@^4.0.0: check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== chokidar@3.3.0: version "3.3.0" @@ -374,6 +443,21 @@ chokidar@3.3.0: optionalDependencies: fsevents "~2.1.1" +chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -400,17 +484,22 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +commander@^9.0.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.3.0.tgz#f619114a5a2d2054e0d9ff1b31d5ccf89255e26b" + integrity sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== cross-spawn@^7.0.2: version "7.0.3" @@ -428,17 +517,31 @@ debug@3.2.6: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== +debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.0.1, debug@^4.1.1, debug@^4.3.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== deep-eql@^3.0.1: version "3.0.1" @@ -448,18 +551,19 @@ deep-eql@^3.0.1: type-detect "^4.0.0" deep-is@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" -diff@3.5.0: +diff@3.5.0, diff@^3.1.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== @@ -476,6 +580,13 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -488,6 +599,11 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + enquirer@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -495,40 +611,46 @@ enquirer@^2.3.5: dependencies: ansi-colors "^4.1.1" -es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: - version "1.17.7" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" - integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== +es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" + integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== dependencies: + call-bind "^1.0.2" es-to-primitive "^1.2.1" function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-regex "^1.1.1" - object-inspect "^1.8.0" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.0" object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" + object.assign "^4.1.2" + regexp.prototype.flags "^1.4.3" + string.prototype.trimend "^1.0.5" + string.prototype.trimstart "^1.0.5" + unbox-primitive "^1.0.2" -es-abstract@^1.18.0-next.0: - version "1.18.0-next.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" - integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-negative-zero "^2.0.0" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -542,23 +664,88 @@ es-to-primitive@^1.2.1: escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== eslint-config-prettier@^6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.13.0.tgz#207d88796b5624e5bb815bbbdfc5891ceb9ebffa" - integrity sha512-LcT0i0LSmnzqK2t764pyIt7kKH2AuuqKRTtJTdddWxOiUja9HdG5GXBVF2gmCTvVYWVsTu8J2MhJLVGRh+pj8w== + version "6.15.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" + integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== dependencies: get-stdin "^6.0.0" +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-module-utils@^2.7.3: + version "2.7.3" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee" + integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== + dependencies: + debug "^3.2.7" + find-up "^2.1.0" + +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-import@^2.26.0: + version "2.26.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" + integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.3" + has "^1.0.3" + is-core-module "^2.8.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.values "^1.1.5" + resolve "^1.22.0" + tsconfig-paths "^3.14.1" + +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + eslint-plugin-prettier@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2" - integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg== + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" + integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== dependencies: prettier-linter-helpers "^1.0.0" -eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-plugin-promise@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz#017652c07c9816413a41e11c30adc42c3d55ff18" + integrity sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw== + +eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -573,39 +760,49 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint-visitor-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" - integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== eslint@^7.11.0: - version "7.11.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.11.0.tgz#aaf2d23a0b5f1d652a08edacea0c19f7fadc0b3b" - integrity sha512-G9+qtYVCHaDi1ZuWzBsOWo2wSwd70TXnU6UHA3cTYHp7gCTXZcpggWFoUVAMRarg68qtPoNfFbzPh+VdOgmwmw== + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== dependencies: - "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.1.3" + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" enquirer "^2.3.5" + escape-string-regexp "^4.0.0" eslint-scope "^5.1.1" eslint-utils "^2.1.0" eslint-visitor-keys "^2.0.0" - espree "^7.3.0" - esquery "^1.2.0" + espree "^7.3.1" + esquery "^1.4.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" + glob-parent "^5.1.2" + globals "^13.6.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" @@ -613,7 +810,7 @@ eslint@^7.11.0: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.19" + lodash.merge "^4.6.2" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -622,17 +819,17 @@ eslint@^7.11.0: semver "^7.2.1" strip-ansi "^6.0.0" strip-json-comments "^3.1.0" - table "^5.2.3" + table "^6.0.9" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" - integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== dependencies: acorn "^7.4.0" - acorn-jsx "^5.2.0" + acorn-jsx "^5.3.1" eslint-visitor-keys "^1.3.0" esprima@^4.0.0: @@ -640,10 +837,10 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" - integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== dependencies: estraverse "^5.1.0" @@ -660,16 +857,16 @@ estraverse@^4.1.1: integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -679,17 +876,16 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.1.1: - version "3.2.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" - integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" + glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" + micromatch "^4.0.4" fast-json-stable-stringify@^2.0.0: version "2.1.0" @@ -699,21 +895,21 @@ fast-json-stable-stringify@^2.0.0: fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" - integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== dependencies: reusify "^1.0.4" -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: - flat-cache "^2.0.1" + flat-cache "^3.0.4" fill-range@^7.0.1: version "7.0.1" @@ -729,14 +925,20 @@ find-up@3.0.0, find-up@^3.0.0: dependencies: locate-path "^3.0.0" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" + locate-path "^2.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" flat@^4.1.0: version "4.1.1" @@ -745,35 +947,55 @@ flat@^4.1.0: dependencies: is-buffer "~2.0.3" -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +flatted@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" + integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== follow-redirects@^1.14.0: - version "1.14.4" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" - integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== + version "1.15.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== get-caller-file@^2.0.1: version "2.0.5" @@ -783,14 +1005,31 @@ get-caller-file@^2.0.1: get-func-name@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" + integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== -glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -810,34 +1049,34 @@ glob@7.1.3: path-is-absolute "^1.0.0" glob@^7.1.3: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== +globals@^13.6.0, globals@^13.9.0: + version "13.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" + integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== dependencies: - type-fest "^0.8.1" + type-fest "^0.20.2" -globby@^11.0.1: - version "11.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" - integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== +globby@^11.0.3, globby@^11.0.4: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" growl@1.10.5: @@ -845,20 +1084,39 @@ growl@1.10.5: resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.0, has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" has@^1.0.3: version "1.0.3" @@ -877,15 +1135,15 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" - integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -893,12 +1151,12 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" @@ -908,6 +1166,22 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -915,66 +1189,117 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-buffer@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" -is-callable@^1.1.4, is-callable@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" - integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== +is-buffer@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-core-module@^2.8.1, is-core-module@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== + dependencies: + has "^1.0.3" is-date-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" - integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" -is-negative-zero@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" - integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-regex@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" - integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: - has-symbols "^1.0.1" + call-bind "^1.0.2" + has-tostringtag "^1.0.0" -is-symbol@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" - integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== dependencies: - has-symbols "^1.0.1" + call-bind "^1.0.2" + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== js-tokens@^4.0.0: version "4.0.0" @@ -990,9 +1315,9 @@ js-yaml@3.13.1: esprima "^4.0.0" js-yaml@^3.13.1: - version "3.14.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" - integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -1002,10 +1327,22 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" levn@^0.4.1: version "0.4.1" @@ -1015,6 +1352,14 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -1023,7 +1368,17 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@^4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -1035,43 +1390,71 @@ log-symbols@3.0.0: dependencies: chalk "^2.4.2" +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.0.5" + braces "^3.0.2" + picomatch "^2.3.1" -minimatch@3.0.4, minimatch@^3.0.4: +minimatch@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" -mkdirp@0.5.5, mkdirp@^0.5.1: +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +mkdirp@0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" +mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + mocha@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" @@ -1107,20 +1490,35 @@ mockery@^2.1.0: resolved "https://registry.yarnpkg.com/mockery/-/mockery-2.1.0.tgz#5b0aef1ff564f0f8139445e165536c7909713470" integrity sha512-9VkOmxKlWXoDO/h1jDZaS4lH33aWfRiJiNT/tKj+8OGzrcFDLo8d0syGdbsc3Bc4GvRXPb+NMMvojotmuGJTvA== +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + ms@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@2.1.2, ms@^2.1.1: +ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mylas@^2.1.9: + version "2.1.11" + resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.11.tgz#1827462533977bed1c4251317aa84254e3ca94c7" + integrity sha512-krnPUl3n9/k52FGCltWMYcqp9SttxjRJEy0sWLk+g7mIa7wnZrmNSZ40Acx7ghzRSOsxt2rEqMbaq4jWlnTDKg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== node-environment-flags@1.0.6: version "1.0.6" @@ -1135,12 +1533,12 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -object-inspect@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" - integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== +object-inspect@^1.12.0, object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -1155,28 +1553,39 @@ object.assign@4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" - integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.18.0-next.0" has-symbols "^1.0.1" object-keys "^1.1.1" object.getownpropertydescriptors@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" - integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + version "2.1.4" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz#7965e6437a57278b587383831a9b829455a4bc37" + integrity sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ== dependencies: + array.prototype.reduce "^1.0.4" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.1" + +object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.19.1" once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -1192,6 +1601,13 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + p-limit@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -1199,6 +1615,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -1206,6 +1629,11 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -1221,32 +1649,44 @@ parent-module@^1.0.0: path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +plimit-lit@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/plimit-lit/-/plimit-lit-1.2.7.tgz#ae16e6e5eadf87924e574337b4c01d140b986c4a" + integrity sha512-ce/kfCHFJ2sIK1IuSnXfVBxoMaIwuAF9J5NjFwxng1j+r8XguGxXMK87dBSODQfY+se2Raj/grpx5EAK9kapEA== + dependencies: + queue-lit "^1.2.8" prelude-ls@^1.2.1: version "1.2.1" @@ -1261,9 +1701,9 @@ prettier-linter-helpers@^1.0.0: fast-diff "^1.1.2" prettier@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" - integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== progress@^2.0.0: version "2.0.3" @@ -1275,6 +1715,16 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +queue-lit@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/queue-lit/-/queue-lit-1.2.8.tgz#2bafa0eafb8db0380ab2301d90c52a065c4baad0" + integrity sha512-CR0/8Xb0oRk4rZrteSZcjrrPhWfXGBAWa/ATxYCqpdM4fnZu8M3zob5ajLxLUCXmpOzhHZ1+zgscrlzQtEOM0A== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + readdirp@~3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" @@ -1282,15 +1732,36 @@ readdirp@~3.2.0: dependencies: picomatch "^2.0.4" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + regexpp@^3.0.0, regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== require-main-filename@^2.0.0: version "2.0.0" @@ -1302,37 +1773,55 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve@^1.10.1, resolve@^1.20.0, resolve@^1.22.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^7.2.1, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== +semver@^6.1.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.2.1, semver@^7.3.5: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== shebang-command@^2.0.0: version "2.0.0" @@ -1346,24 +1835,33 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" -source-map-support@^0.5.17: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== +source-map-support@^0.5.17, source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -1376,7 +1874,7 @@ source-map@^0.6.0: sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== "string-width@^1.0.2 || 2": version "2.1.1" @@ -1395,26 +1893,37 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string.prototype.trimend@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" -string.prototype.trimstart@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== +string.prototype.trimend@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" + integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + +string.prototype.trimstart@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" + integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== dependencies: ansi-regex "^3.0.0" @@ -1425,17 +1934,22 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - ansi-regex "^5.0.0" + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-json-comments@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" @@ -1463,20 +1977,26 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +table@^6.0.9: + version "6.8.0" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" + integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA== dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== to-regex-range@^5.0.1: version "5.0.1" @@ -1485,6 +2005,29 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +ts-mocha@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" + integrity sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw== + dependencies: + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" + ts-node@^8.10.1: version "8.10.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" @@ -1496,15 +2039,37 @@ ts-node@^8.10.1: source-map-support "^0.5.17" yn "3.1.1" +tsc-alias@^1.6.11: + version "1.6.11" + resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.6.11.tgz#d6d83f030ad11f48e4ead8ec5729929e5e60519b" + integrity sha512-mXEM21WriTJMQyo07B4Kc2nNFFk/1qOjU+jZ0ymXOyLz/A8J+dIBkimqZrh3s/x1qLGoJ1cNZQxa8GGoWOGX1Q== + dependencies: + chokidar "^3.5.3" + commander "^9.0.0" + globby "^11.0.4" + mylas "^2.1.9" + normalize-path "^3.0.0" + plimit-lit "^1.2.6" + +tsconfig-paths@^3.14.1, tsconfig-paths@^3.5.0: + version "3.14.1" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" + integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.6" + strip-bom "^3.0.0" + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tsutils@^3.17.1: - version "3.17.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" - integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -1520,32 +2085,53 @@ type-detect@^4.0.0, type-detect@^4.0.5: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -typescript@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5" - integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== +typescript@^4.7.4: + version "4.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" v8-compile-cache@^2.0.3: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" - integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== which@1.3.1: version "1.3.1" @@ -1585,19 +2171,17 @@ wrap-ansi@^5.1.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== y18n@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" - integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yargs-parser@13.1.2, yargs-parser@^13.1.2: version "13.1.2" @@ -1636,3 +2220,8 @@ yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==