diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..39ac70e40f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +docs/launch.json linguist-language=JSON5 +.nycrc linguist-language=JSON +.prettierrc linguist-language=JSON diff --git a/.github/ganache-logo-dark.svg b/.github/ganache-logo-dark.svg new file mode 100644 index 0000000000..3746549d85 --- /dev/null +++ b/.github/ganache-logo-dark.svg @@ -0,0 +1 @@ +ganache-logo-v-dark \ No newline at end of file diff --git a/.github/truffle-logo-dark.svg b/.github/truffle-logo-dark.svg new file mode 100644 index 0000000000..92900f899f --- /dev/null +++ b/.github/truffle-logo-dark.svg @@ -0,0 +1 @@ +truffle-logo-dark \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000000..64bddedb1b --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,52 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: CI + +on: [push, pull_request] + +jobs: + build: + strategy: + fail-fast: false + matrix: + node: [10.7.0, 10.x, 11.x, 12.x, 13.x, 14.x] + os: + [ + windows-2016, + windows-2019, + ubuntu-16.04, + ubuntu-18.04, + ubuntu-20.04, + macos-11.0, + ] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + # we need build tools for the `bigint-buffer` module + - name: Add msbuild to PATH + if: startsWith(matrix.os, 'windows-') + uses: microsoft/setup-msbuild@v1.0.2 + - name: install node tools + if: startsWith(matrix.os, 'windows-') + # windows-build-tools@5.2.2 failed to install, so we use 4.0.0 + run: npm install --global --production windows-build-tools@4.0.0 + - name: install node-gyp + if: startsWith(matrix.os, 'windows-') + run: npm install --global node-gyp@latest + - name: Set node config to use python2.7 + if: startsWith(matrix.os, 'windows-') + run: npm config set python python2.7 + - name: Set node config to set msvs_version to 2015 + if: startsWith(matrix.os, 'windows-') + run: npm config set msvs_version 2015 + - run: npm ci + - run: npm test + env: + FORCE_COLOR: 1 diff --git a/.gitignore b/.gitignore index 5a759832bd..84795d7c22 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ node_modules -TODO -*.log -.eslintrc.js -.tern-project .DS_Store -.tern-port .vscode -build \ No newline at end of file +.nyc_output +lerna-debug.log +npm-debug.log +src/**/*/lib +coverage +dist/ diff --git a/.npmignore b/.npmignore deleted file mode 100644 index a8b1202e89..0000000000 --- a/.npmignore +++ /dev/null @@ -1,13 +0,0 @@ -.npmignore -.tern-project -.tern-port -.dockerignore -.travis.yml -.eslintrc.js -*.log -Dockerfile -ISSUE_TEMPLATE.md -.vscode/ -test/ -webpack/ -perf/ \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000000..eb29e2d5fe --- /dev/null +++ b/.npmrc @@ -0,0 +1,6 @@ +engine-strict=true +save-exact=true +sign-git-commit=true +sign-git-tag=true +loglevel=error +fund=false diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..a63bb50634 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v10.7.0 diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000000..0395a09274 --- /dev/null +++ b/.nycrc @@ -0,0 +1,3 @@ +{ + "extends": "@istanbuljs/nyc-config-typescript" +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..43ecbd0792 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +.DS_Store +.vscode +.nyc_output +lerna-debug.log +npm-debug.log +src/**/*/lib +coverage +npm-shrinkwrap.json diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000..1f5e5d140d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "arrowParens": "avoid", + "trailingComma": "none" +} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 32eba855c1..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -language: node_js -node_js: - - "node" - - "lts/carbon" - -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-5 - - g++-5 - -before_install: - - if [ $TRAVIS_OS_NAME == "linux" ]; then - export CC="gcc-5"; - export CXX="g++-5"; - export LINK="gcc-5"; - export LINKXX="g++-5"; - fi - - nvm --version - - node --version - - npm --version - - gcc --version - - g++ --version diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..b55bdff3f9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,145 @@ +# Contributing to Ganache + +## Getting set up + +- Use Node.js v10.7.0, this is the earliest version we support. + - Why v10.7.0? Because this is the first version that supports BigInt literals (the `n` in `100n`). + - recommendation: use [nvm](https://github.com/nvm-sh/nvm) on Linux and macOS, and [nvm-windows](https://github.com/coreybutler/nvm-windows) on + Windows, to configure your node version. + - On Linux and macOS, if you have `nvm` installed, just run `nvm use` to switch to Node.js v10.7.0. +- `git clone git@github.com:trufflesuite/ganache-core.git` +- `cd ganache-core` +- `npm install` (use npm v6) +- On Linux and macOS: run `source completions.sh` to enable autocomplete for npm scripts. + +## Solving node-gyp issues + +If installation fails due to a `node-gyp` issue you may need to perform some additional system configuration. + +### on Linux (Ubuntu-based) + +- Determine if you have Python 2.7 installed + - example: `which python2.7` +- If you do not have Python 2.7 installed, you need to install it + - example: `sudo apt update && sudo apt install python2.7` +- Finally, run `npm config set python python2.7` + +### on Windows + +- Install [https://www.npmjs.com/package/windows-build-tools](Windows-Build-Tools) + - `npm install --global windows-build-tools` + +### On macOS + +- I have no idea. + +## Clean install + +- `npm run reinstall` + +Which just runs these commands for you: + +- `npm run clean` +- `npm install` + +This deletes all `node_modules` folders, as well as all generated `lib` +directories, then reinstalls all modules. + +## To build + +Builds all packages: + +- `npm run tsc` + +## To test + +Runs all tests: + +- `npm test` (or the shorthand, `npm t`) + +## To create a new package + +- `npm run create --location ` + +This will create a new package with Ganache defaults at `src//`. + +## To add a module to a package: + +- `npx lerna add [@version] -E [--dev] [--peer] --scope=` + +Where `` is the npm-module you want to add and `` is where you want to add it. See +[@lerna/add documentation](https://github.com/lerna/lerna/tree/master/commands/add) for more details. + +Example: + +```bash +npx lerna add @ganache/options -E --scope=@ganache/filecoin +``` + +will add our local `@ganache/options` package to the `@ganache/filecoin` package. + +## To remove a module from another package: + +`cd` to the package and then run `npm uninstall ` + +## Editor Integrations + +### Automated Code Formatting + +- See: https://prettier.io/docs/en/editors.html + +### VSCode On Windows (10) + +- Enable "Developer Mode" by going to Settings -> Developer Settings -> Then select Developer Mode. + +### To debug tests in VS Code + +- Copy the [`launch.json`](./launch.json) file into a folder named `.vscode` in root of the project. +- Set breakpoints by clicking the margin to the left of the line numbers (you can set conditional breakpoints or + logpoints by right-clicking instead) +- Press F5 (or select `Run` 🡺 `Start Debugging` from the menu bar) to automatically start debugging. + +To change which files are debugged update your `.vscode/launch.json` file glob to match your target files. Here is an +example to debug only test files in the `@ganache/ethereum` package: + +```diff +diff --git a/.vscode/launch.json b/.vscode/launch.json +index 2a2aa9e..57cbf21 100644 +--- a/.vscode/launch.json ++++ b/.vscode/launch.json +@@ -24,7 +24,7 @@ + "--colors", + "--require", + "ts-node/register", +- "${workspaceFolder}/src/**/tests/**/*.test.ts" ++ "${workspaceFolder}/src/chains/ethereum/tests/**/*.test.ts" + ], + "skipFiles": ["/**"], + "console": "integratedTerminal", +``` + +## Code Conventions + +These are guidelines, not rules. :-) + +- Use Node.js v10.7.0 for most local development. +- Use `bigint` literals, e.g., `123n`; if the number is externally configurable and/or could exceed + `Number.MAX_SAFE_INTEGER`. +- Write tests. +- Do not use "Optional Chaining" (`obj?.prop`). I'd love to enable this, but TypeScript makes it hard to use bigint + literals and optional chaining together. If you figure it out, delete this rule! +- Prefer using a single loop to functional chaining. +- Prefer performant code over your own developer experience. +- Document complex code. Explain why the code does what it does. +- Feel free to be clever, just document _why_ you're being clever. If it's hard to read, comment _what_ the code does, + too. +- Add JSDoc comments to public class members where it makes sense. +- Before adding an external dependency check its code for quality, its # of external dependencies, its node version + support, and make sure it's absolutely necessary. +- Pin all dependencies, even dev dependencies. +- Use npm; do not use yarn. +- Don't use web3, ethers, etc in ganache-core core code. (Tests are fine) +- Ensure a smooth development experience on Windows, Mac, and Linux. +- Do not use bash scripts for critical development or configuration. +- Do not use CLI commands in npm scripts or build scripts that aren't available by default on supported platforms. +- Push your code often (at least every-other day!), even broken WIP code (to your own branch, of course). diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index b621f54072..0000000000 --- a/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM mhart/alpine-node:7.9.0 - -RUN apk add --no-cache make gcc g++ python git bash -COPY package.json /src/package.json -WORKDIR /src -RUN npm install - -ADD . . - -EXPOSE 8545 - -ENTRYPOINT ["node", "./bin/testrpc"] diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index 4d096d2025..0000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - -## Expected Behavior - - - -## Current Behavior - - - -## Possible Solution - - - -## Steps to Reproduce (for bugs) - - -1. -2. -3. -4. - -## Context - - - -## Your Environment - -* Version used: -* Environment name and version (e.g. PHP 5.4 on nginx 1.9.1): -* Server type and version: -* Operating System and version: -* Link to your project: diff --git a/LICENSE b/LICENSE index a5a4e4d44a..39f3b14498 100644 --- a/LICENSE +++ b/LICENSE @@ -1,22 +1,21 @@ The MIT License (MIT) -Copyright (c) 2015 Iuri Matias +Copyright (c) 2019-2020 Truffle Blockchain Group -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/README.md b/README.md index e9cfb11029..65d380f5d3 100644 --- a/README.md +++ b/README.md @@ -1,143 +1,211 @@ -[![npm](https://img.shields.io/npm/v/ganache-core.svg)]() -[![npm](https://img.shields.io/npm/dm/ganache-core.svg)]() -[![Build Status](https://travis-ci.org/trufflesuite/ganache-core.svg?branch=master)](https://travis-ci.org/trufflesuite/ganache-core) -# Ganache Core +

+ Ganache +

-This is the core code that powers the Ganache application and the the Ganache command line tool. +

+ A tool for creating a local blockchain for fast Ethereum development. +

-# INSTALL +

+ + + +

-`ganache-core` is written in Javascript and distributed as a Node package via `npm`. Make sure you have Node.js (>= v8.9.0) installed, and your environment is capable of installing and compiling `npm` modules. +

+ Features • + Getting Started • + Documentation • + Community • + Contributing • + Related +

-**macOS** Make sure you have the XCode Command Line Tools installed. These are needed in general to be able to compile most C based languages on your machine, as well as many npm modules. +--- -**Windows** See our [Windows install instructions](https://github.com/ethereumjs/testrpc/wiki/Installing-TestRPC-on-Windows). +## Features -**Ubuntu/Linux** Follow the basic instructions for installing [Node.js](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions) and make sure that you have `npm` installed, as well as the `build-essential` `apt` package (it supplies `make` which you will need to compile most things). Use the official Node.js packages, *do not use the package supplied by your distribution.* +Ganache is an Ethereum simulator that makes developing Ethereum applications faster, easier, and safer. It includes all popular RPC functions and features (like events) and can be run deterministically to make development a breeze. +- Fork any Ethereum network without waiting to sync +- Ethereum json-rpc support +- Snapshot/revert state +- Mine blocks instantly, on demand, or at an interval +- Fast-forward time +- Impersonate any account (no private keys required!) +- Listens for JSON-RPC 2.0 requests over HTTP/WebSockets +- Programmatic use in Node.js +- Pending Transactions -```Bash -npm install ganache-core +## Getting Started + +Ganache can be used from the command line or programmatically via Node.js. + +### Command line use + +You must first install [Node.js](https://nodejs.org/) >= v10.7.0 and npm >= 6.1.0. + +To install ganache-cli globally, run: + +```console +$ npm install ganache-cli --global +``` + +Once installed globally, you can start ganache-cli right from your command line: + +```console +$ ganache-cli +Ganache CLI v6.12.1 (ganache-core: 2.13.1) + +Available Accounts +================== +(0) 0x665a72A5A58c8ecD51dBC913f18286a104Ff6F8d (100 ETH) +(1) 0x990Ca50F8Ac586384594a98EDaB3F8b46CEd179c (100 ETH) +(2) 0x5c49b8831C81C4aa572d2733Ea7619e2fbaE7bb2 (100 ETH) +(3) 0xb3eFA990367077B0b74150B74E8D6520E692bD82 (100 ETH) +(4) 0xEb9D56915a83F7f2FEA6B18C702cD24D6a07fD62 (100 ETH) +(5) 0x8A199Adfd3D2fB10430f8D006cfd79b28D7D6562 (100 ETH) +(6) 0x2964eCA6615534E59b94FBf642d73Bcc09C7D835 (100 ETH) +(7) 0x255dE55cA7040D4ada06295F89Af5a3d7204f751 (100 ETH) +(8) 0x946790395bB4C0f6a6cEDD90D04D0023c3Bf256B (100 ETH) +(9) 0xddAeCA7f5d58539c9f78F64e8Be4bD437e6E085a (100 ETH) + +Private Keys +================== +(0) 0x3b1f1c5750edbda54702bcd70d2f0925f38c77269d606bd0faad2369aa834770 +(1) 0xdd09ee23ec00b5a6c24d954d9b333411c0ad830c1edc4dec0d625c532785e621 +(2) 0x71edfcf731f142526f2a9adee826775b2ae512d7a65de7ae65fd074e0c7053a9 +(3) 0x66ad9dd75f1fc73582a09c6da31ededec8df138db0acd02285792e9c29cd6711 +(4) 0xa0a728215cbf24a62edfef3ecfdc5b137b18b4a07fa2502d4f21f705f898c5a4 +(5) 0x9003b737d388eff793d308302c2e484f339c417e727e213cc46b7cd3f29dcef5 +(6) 0xe8de8c5ee8643699f344cefb0c502e6081422fc012bd50274007dd167147a4e6 +(7) 0xdf5df29263acd5b327db6870798856c2abab31262c83b5801ab4851297326266 +(8) 0x2bb1e1a8372370ac758795c26a6cf1f015b89d05079a8750616cd1b61d93d3bb +(9) 0xbaa9325adb6a75b1177700130aed2281b1eb1fcfac5203c14a8cabf0f82e71d3 + +HD Wallet +================== +Mnemonic: charge bamboo worry unaware rude drink congress mushroom exile federal typical couple +Base HD Path: m/44'/60'/0'/0/{account_index} + +Gas Price +================== +20000000000 + +Gas Limit +================== +6721975 + +Call Gas Limit +================== +9007199254740991 + +Listening on 127.0.0.1:8545 +``` + +To install ganache-cli into an npm project, run: + +```console +$ npm install ganache-cli +``` + +You can then add ganache-cli to your package.json scripts: + +```json +"scripts": { + "ganache": "ganache-cli --seed myCustomSeed" +} +``` + +_See [Documentation](#documentation) for additional command line options._ + +then start it: + +```console +$ npm run ganache +``` + +### Programmatic use + +You can use ganache-cli programmatically from Node.js. Install ganache-cli into your npm package: + +```console +$ npm install ganache-cli ``` -# USAGE +then start ganache as an EIP-1193 provider only: -As a Web3 provider: +```javascript +const ganache = require("ganache-cli"); + +const options = {}; +const provider = ganache.provider(options); +const accounts = await provider.request({ method: "eth_accounts", params: [] }); +``` + +or as an EIP-1193 provider _and_ JSON-RPC web server: ```javascript -var Ganache = require("ganache-core"); -web3.setProvider(Ganache.provider()); +const ganache = require("ganache-cli"); + +const options = {}; +const server = ganache.server(options); +const PORT = 8545; +server.listen(PORT, err => { + if (err) throw err; + + console.log(`ganache-cli listening on port ${PORT}...`); + const provider = server.provider; + const accounts = await provider.request({ method: "eth_accounts", params:[] }); +}); ``` -As a general http server: +#### As a [web3.js](https://www.npmjs.com/package/web3) Provider + +To use ganache as a Web3 provider: ```javascript -var Ganache = require("ganache-core"); -var server = Ganache.server(); -server.listen(port, function(err, blockchain) {...}); +const Web3 = require("web3"); +const ganache = require("ganache-cli"); + +const web3 = new Web3(ganache.provider()); ``` -Both `.provider()` and `.server()` take a single object which allows you to specify behavior of the Ganache instance. This parameter is optional. Available options are: - -* `"accounts"`: `Array` of `Object`'s. Each object should have a balance key with a hexadecimal value. The key `secretKey` can also be specified, which represents the account's private key. If no `secretKey`, the address is auto-generated with the given balance. If specified, the key is used to determine the account's address. -* `"debug"`: `boolean` - Output VM opcodes for debugging -* `"logger"`: `Object` - Object, like `console`, that implements a `log()` function. -* `"mnemonic"`: Use a specific HD wallet mnemonic to generate initial addresses. -* `"port"`: Port number to listen on when running as a server. -* `"seed"`: Use arbitrary data to generate the HD wallet mnemonic to be used. -* `"default_balance_ether"`: `number` - The default account balance, specified in ether. -* `"total_accounts"`: `number` - Number of accounts to generate at startup. -* `"fork"`: `string` or `object` - When a `string`, same as `--fork` option above. Can also be a Web3 Provider object, optionally used in conjunction with the `fork_block_number` option below. -* `"fork_block_number"`: `string` or `number` - Block number the provider should fork from, when the `fork` option is specified. If the `fork` option is specified as a string including the `@` sign and a block number, the block number in the `fork` parameter takes precedence. -* `"network_id"`: `integer` - Same as `--networkId` option above. -* `"time"`: `Date` - Date that the first block should start. Use this feature, along with the `evm_increaseTime` method to test time-dependent code. -* `"locked"`: `boolean` - whether or not accounts are locked by default. -* `"unlocked_accounts"`: `Array` - array of addresses or address indexes specifying which accounts should be unlocked. -* `"db_path"`: `String` - Specify a path to a directory to save the chain database. If a database already exists, that chain will be initialized instead of creating a new one. -* `"db"`: `Object` - Specify an alternative database instance, for instance [MemDOWN](https://github.com/level/memdown). -* `"ws"`: Enable a websocket server. This is `true` by default. -* `"vmErrorsOnRPCResponse"`: Whether to report runtime errors from EVM code as RPC errors. This is `true` by default to replicate the error reporting behavior of previous versions of ganache. -* `"hdPath"`: The hierarchical deterministic path to use when generating accounts. Default: "m/44'/60'/0'/0/" -* `"allowUnlimitedContractSize"`: Allows unlimited contract sizes while debugging. By setting this to `true`, the check within the EVM for contract size limit of 24KB (see [EIP-170](https://git.io/vxZkK)) is bypassed. Setting this to `true` **will** cause `ganache-core` to behave differently than production environments. (default: `false`; **ONLY** set to `true` during debugging). -* `"gasPrice"`: Sets the default gas price for transactions if not otherwise specified. Must be specified as a hex string in wei. Defaults to `"0x77359400"`, or 2 gwei. -* `"gasLimit"`: Sets the block gas limit. Must be specified as a hex string. Defaults to `"0x6691b7"`. - -# IMPLEMENTED METHODS - -The RPC methods currently implemented are: - -* `bzz_hive` (stub) -* `bzz_info` (stub) -* `debug_traceTransaction` -* `eth_accounts` -* `eth_blockNumber` -* `eth_call` -* `eth_coinbase` -* `eth_estimateGas` -* `eth_gasPrice` -* `eth_getBalance` -* `eth_getBlockByNumber` -* `eth_getBlockByHash` -* `eth_getBlockTransactionCountByHash` -* `eth_getBlockTransactionCountByNumber` -* `eth_getCode` (only supports block number “latest”) -* `eth_getCompilers` -* `eth_getFilterChanges` -* `eth_getFilterLogs` -* `eth_getLogs` -* `eth_getStorageAt` -* `eth_getTransactionByHash` -* `eth_getTransactionByBlockHashAndIndex` -* `eth_getTransactionByBlockNumberAndIndex` -* `eth_getTransactionCount` -* `eth_getTransactionReceipt` -* `eth_hashrate` -* `eth_mining` -* `eth_newBlockFilter` -* `eth_newFilter` (includes log/event filters) -* `eth_protocolVersion` -* `eth_sendTransaction` -* `eth_sendRawTransaction` -* `eth_sign` -* `eth_subscribe` (only for websocket connections. "syncing" subscriptions are not yet supported) -* `eth_unsubscribe` (only for websocket connections. "syncing" subscriptions are not yet supported) -* `eth_syncing` -* `eth_uninstallFilter` -* `net_listening` -* `net_peerCount` -* `net_version` -* `miner_start` -* `miner_stop` -* `personal_listAccounts` -* `personal_lockAccount` -* `personal_newAccount` -* `personal_importRawKey` -* `personal_unlockAccount` -* `personal_sendTransaction` -* `shh_version` -* `rpc_modules` -* `web3_clientVersion` -* `web3_sha3` - -There’s also special non-standard methods that aren’t included within the original RPC specification: - -* `evm_snapshot` : Snapshot the state of the blockchain at the current block. Takes no parameters. Returns the integer id of the snapshot created. -* `evm_revert` : Revert the state of the blockchain to a previous snapshot. Takes a single parameter, which is the snapshot id to revert to. If no snapshot id is passed it will revert to the latest snapshot. Returns `true`. -* `evm_increaseTime` : Jump forward in time. Takes one parameter, which is the amount of time to increase in seconds. Returns the total time adjustment, in seconds. -* `evm_mine` : Force a block to be mined. Takes one optional parameter, which is the timestamp a block should setup as the mining time. Mines a block independent of whether or not mining is started or stopped. - -# Unsupported Methods - -* `eth_compileSolidity`: If you'd like Solidity compilation in Javascript, please see the [solc-js project](https://github.com/ethereum/solc-js). - - -# TESTING - -Run tests via: +NOTE: depending on your web3 version, you may need to set a number of confirmation blocks ``` -$ npm test +const web3 = new Web3(ganache.provider(), null, { transactionConfirmationBlocks: 1 }); +``` + +#### As an [ethers.js]() provider: + +```javascript +const ganache = require("ganache-cli"); + +const provider = new ethers.providers.Web3Provider(ganache.provider()); ``` -# LICENSE -[MIT](https://tldrlegal.com/license/mit-license) +## Documentation + +TODO + +## Community + +TODO + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for our guide to contributing to ganache. + +## Related + +- [Truffle](https://www.github.com/trufflesuite/truffle) +- [Drizzle](https://www.github.com/trufflesuite/drizzle) + +
+ +--- + +

+ Truffle +

diff --git a/completions.sh b/completions.sh new file mode 100644 index 0000000000..98b265cf29 --- /dev/null +++ b/completions.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +_npmScriptsCompletions() { + local cur_word args type_list first_arg + + cur_word="${COMP_WORDS[COMP_CWORD]}" + args=("${COMP_WORDS[@]}") + + if [ "${COMP_WORDS[1]}" == "run" ] && [ ${#COMP_WORDS[@]} == 3 ]; then + # get a list of all npm scripts and add them to the bash autocomplete reply + type_list=$(node -e "console.log(Object.keys(require('./package.json').scripts).join('\n'))") + COMPREPLY=($(compgen -W "${type_list}" -- ${cur_word})) + else + # if the command if the create command (npm run create) get its completion values + if [ "${COMP_WORDS[1]}" == "run" ] && [ "${COMP_WORDS[2]}" == "create" ]; then + while [[ "$#" -gt 0 ]]; do + case $1 in + -l | --location) + type_list=$(ls src) + shift + ;; + - | --l | --lo | --loc | --loca | --locat | --locati | --locatio) + # autocomplete "-l" or "--location" (but only when we don't already have the full word) + if [[ ! " ${COMP_WORDS[@]} " =~ " --location " ]] && [[ ! " ${COMP_WORDS[@]} " =~ " -l " ]]; then + type_list="--location" + fi + shift + ;; + *) shift ;; + esac + done + + COMPREPLY=($(compgen -W "${type_list}" -- ${cur_word})) + fi + fi + return 0 +} +complete -o default -F _npmScriptsCompletions npm diff --git a/docs/launch.json b/docs/launch.json new file mode 100644 index 0000000000..5022ee3196 --- /dev/null +++ b/docs/launch.json @@ -0,0 +1,34 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Typescript Mocha All", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "env": { + "TS_NODE_COMPILER": "ttypescript", + "TS_NODE_FILES": "true" + }, + // 10.7.0 is the earliest version of Node.js that we support, and is the first version to support BigInt literals. + "runtimeVersion": "10.7.0", + "args": [ + "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "--throw-deprecation", + "--trace-warnings", + "--check-leaks", + "--no-timeout", + "--colors", + "--require", + "ts-node/register", + "${workspaceFolder}/src/**/tests/**/*.test.ts" + ], + "skipFiles": ["/**"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + } + ] +} diff --git a/index.js b/index.js deleted file mode 100644 index 4b721c4a2b..0000000000 --- a/index.js +++ /dev/null @@ -1,35 +0,0 @@ -// make sourcemaps work! -require("source-map-support/register"); - -const debug = require("debug")("ganache"); - -// we use optional dependencies which may, or may not exist, so try native first -try { - // make sure these exist before we try to load ganache with native modules - const optionalDependencies = require("./package.json").optionalDependencies; - const wrongWeb3 = require("web3/package.json").version !== optionalDependencies["web3"]; - const wrongEthereumJs = require("ethereumjs-wallet/package.json").version !== optionalDependencies["ethereumjs-wallet"]; - if (wrongWeb3 || wrongEthereumJs) { - useBundled(); - } else { - module.exports = require("./public-exports.js"); - module.exports._webpacked = false; - debug("Optional dependencies installed; exporting ganache-core with native optional dependencies."); - } -} catch (nativeError) { - debug(nativeError); - - // grabbing the native/optional deps failed, try using our webpacked build. - useBundled(); -} - -function useBundled() { - try { - module.exports = require("./build/ganache.core.node.js"); - module.exports._webpacked = true; - debug("Optional dependencies not installed; exporting ganache-core from `./build` directory."); - } catch(webpackError) { - debug("ganache-core could not be exported; optional dependencies nor webpack build available for export."); - throw webpackError; - } -} \ No newline at end of file diff --git a/lerna.json b/lerna.json new file mode 100644 index 0000000000..f53127ee45 --- /dev/null +++ b/lerna.json @@ -0,0 +1,4 @@ +{ + "packages": ["src/packages/*", "src/chains/*"], + "version": "independent" +} diff --git a/lib/block_tracker.js b/lib/block_tracker.js deleted file mode 100644 index edaba0d601..0000000000 --- a/lib/block_tracker.js +++ /dev/null @@ -1,66 +0,0 @@ -// this replaces `eth-block-tracker` in the provider-engine, as that block tracker is meant to work with -// an external provider instance - -const EventEmitter = require('events') -const BlockSerializer = require('./database/blockserializer') -var blockHelper = require('./utils/block_helper'); -const to = require('./utils/to') - -function GanacheBlockTracker(opts) { - opts = opts || {} - EventEmitter.apply(this) - if (!opts.blockchain) throw new Error('RpcBlockTracker - no blockchain specified.') - if (!opts.blockchain.on) throw new Error('RpcBlockTracker - blockchain is not an EventEmitter.') - this._blockchain = opts.blockchain - this.start = this.start.bind(this) - this.stop = this.stop.bind(this) - this.getTrackingBlock = this.getTrackingBlock.bind(this) - this.awaitCurrentBlock = this.awaitCurrentBlock.bind(this) - this._setCurrentBlock = this._setCurrentBlock.bind(this) -} - -GanacheBlockTracker.prototype = Object.create(EventEmitter.prototype) -GanacheBlockTracker.prototype.constructor = GanacheBlockTracker - -GanacheBlockTracker.prototype.getTrackingBlock = function() { - return this._currentBlock -} - -GanacheBlockTracker.prototype.getCurrentBlock = function() { - return this._currentBlock -} - -GanacheBlockTracker.prototype.awaitCurrentBlock = function() { - const self = this - // return if available - if (this._currentBlock) return this._currentBlock - // wait for "sync" event - return new Promise(resolve => this.once('block', resolve)) - .then(() => self._currentBlock) -} - -GanacheBlockTracker.prototype.start = function(opts = {}) { - this._blockchain.on('block', this._setCurrentBlock) - return Promise.resolve() -} - -GanacheBlockTracker.prototype.stop = function() { - this._isRunning = false - this._blockchain.removeListener('block', this._setCurrentBlock) -} - - // - // private - // - -GanacheBlockTracker.prototype._setCurrentBlock = function(newBlock) { - let block = blockHelper.toJSON(newBlock, true) - if (this._currentBlock && (this._currentBlock.hash === block.hash)) return - const oldBlock = this._currentBlock - this._currentBlock = block - this.emit('latest', block) - this.emit('sync', { block, oldBlock }) - this.emit('block', block) -} - -module.exports = GanacheBlockTracker diff --git a/lib/blockchain_double.js b/lib/blockchain_double.js deleted file mode 100644 index 24d2481684..0000000000 --- a/lib/blockchain_double.js +++ /dev/null @@ -1,1085 +0,0 @@ -var to = require("./utils/to.js"); -var Account = require('ethereumjs-account'); -var Block = require('ethereumjs-block'); -var Log = require("./utils/log"); -var Receipt = require("./utils/receipt"); -var VM = require('ethereumjs-vm'); -var RuntimeError = require("./utils/runtimeerror"); -var Trie = require("merkle-patricia-tree"); -var Web3 = require("web3"); -var utils = require("ethereumjs-util"); -var async = require('async'); -var Heap = require("heap"); -var Database = require("./database"); -var EventEmitter = require("events"); -var _ = require('lodash') - -function BlockchainDouble(options) { - var self = this; - EventEmitter.apply(self) - - this.options = options = this._applyDefaultOptions(options || {}); - - this.logger = options.logger || console; - - this.data = new Database(options); - - if (options.trie != null && options.db_path != null) { - throw new Error("Can't initialize a TestRPC with a db and a custom trie."); - } - - this.pending_transactions = []; - - // updated periodically to keep up with the times - this.blockGasLimit = options.gasLimit; - this.defaultTransactionGasLimit = options.defaultTransactionGasLimit; - this.timeAdjustment = 0; -}; - -const defaultOptions = { - gasLimit: "0x6691b7", - defaultTransactionGasLimit: '0x15f90', - time: null, - debug: false, - allowUnlimitedContractSize: false -} - -// inheritence w/ prototype chaining -BlockchainDouble.prototype = Object.create(EventEmitter.prototype); -BlockchainDouble.prototype.constructor = BlockchainDouble; - -BlockchainDouble.prototype._applyDefaultOptions = function(options) { - // We want this function to mutate the options object so that we can report - // our settings back to our consumer application (e.g., ganache) - return _.merge(options, defaultOptions, Object.assign({}, options)); -} - -BlockchainDouble.prototype.initialize = function(accounts, callback) { - var self = this; - - this.data.initialize(function(err) { - if (err) return callback(err); - - self.latestBlock(function(err, block) { - if (err) return callback(err); - - var options = self.options; - - var root = null; - - if (block) { - root = block.header.stateRoot; - } - - // I haven't yet found a good way to do this. Getting the trie from the - // forked blockchain without going through the other setup is a little gross. - self.stateTrie = self.createStateTrie(self.data.trie_db, root); - - self.vm = options.vm || new VM({ - state: self.stateTrie, - blockchain: { - // EthereumJS VM needs a blockchain object in order to get block information. - // When calling getBlock() it will pass a number that's of a Buffer type. - // Unfortunately, it uses a 64-character buffer (when converted to hex) to - // represent block numbers as well as block hashes. Since it's very unlikely - // any block number will get higher than the maximum safe Javascript integer, - // we can convert this buffer to a number ahead of time before calling our - // own getBlock(). If the conversion succeeds, we have a block number. - // If it doesn't, we have a block hash. (Note: Our implementation accepts both.) - getBlock: function(number, done) { - try { - number = to.number(number) - } catch (e) { - // Do nothing; must be a block hash. - } - - self.getBlock(number, done) - } - }, - enableHomestead: true, - activatePrecompiles: true, - allowUnlimitedContractSize: options.allowUnlimitedContractSize - }); - - if (options.debug == true) { - // log executed opcodes, including args as hex - self.vm.on('step', function(info) { - var name = info.opcode.name; - var argsNum = info.opcode.in; - if (argsNum) { - var args = info.stack.slice(-argsNum) - .map((arg) => to.hex(arg)) - .join(' '); - - self.logger.log(`${name} ${args}`); - } else { - self.logger.log(name); - } - }); - } - - if (options.time) { - self.setTime(options.time); - } - - // If we already have a block, then that means there's an existing chain. - // Don't create a genesis block. - if (block) { - self.emit('block', block); - return callback(); - } - - self.createGenesisBlock(function(err, block) { - if (err) return callback(err); - - accounts = accounts || []; - - async.eachSeries(accounts, function(account_data, finished) { - self.putAccount(account_data.account, account_data.address, finished); - }, function(err) { - if (err) return callback(err); - - // Create first block - self.putBlock(block, [], [], callback); - }); - }); - }); - - }); -}; - -BlockchainDouble.prototype.createStateTrie = function(db, root) { - return new Trie(this.data.trie_db, root); -}; - -// Overrideable so other implementations (forking) can edit it. -BlockchainDouble.prototype.createGenesisBlock = function(callback) { - this.createBlock(callback); -}; - -BlockchainDouble.prototype.latestBlock = function(callback) { - this.data.blocks.last(function(err, last) { - if (err) return callback(err); - callback(null, last); - }); -} - -// number accepts number (integer, hex) or tag (e.g., "latest") -BlockchainDouble.prototype.getEffectiveBlockNumber = function(number, callback) { - if (typeof number != "string") { - number = to.hex(number); - } - - // If we have a hex number - if (number.indexOf("0x") >= 0) { - return callback(null, to.number(number)); - } else { - if (number == "latest" || number == "pending") { - return this.getHeight(callback); - } else if (number == "earliest") { - return callback(null, 0); - } - } -}; - -// number accepts number (integer, hex), tag (e.g., "latest") or block hash -// This function is used by ethereumjs-vm -BlockchainDouble.prototype.getBlock = function(number, callback) { - var self = this; - - if (typeof number != "string") { - number = to.hex(number); - } - - // If we have a hex number or a block hash - if (number.indexOf("0x") >= 0) { - var hash = number; - - // block hash - if (hash.length > 40) { - this.data.blockHashes.get(to.hex(hash), function(err, blockIndex) { - if (err) return callback(err); - return self.data.blocks.get(blockIndex, callback); - }); - } else { - // Block number - return this.data.blocks.get(to.number(hash), callback); - } - } else { - if (number == "latest" || number == "pending") { - return this.latestBlock(callback); - } else if (number == "earliest") { - return this.data.blocks.first(callback); - } - } -}; - -BlockchainDouble.prototype.putBlock = function(block, logs, receipts, callback) { - var self = this; - - // Lock in the state root for this block. - block.header.stateRoot = this.stateTrie.root; - - this.data.blocks.length(function(err, length) { - if (err) return callback(err); - - var requests = [ - self.data.blocks.push.bind(self.data.blocks, block), - self.data.blockLogs.push.bind(self.data.blockLogs, logs), - self.data.blockHashes.set.bind(self.data.blockHashes, to.hex(block.hash()), length), - ]; - - block.transactions.forEach(function(tx, index) { - var tx_hash = to.hex(tx.hash()); - - requests.push( - self.data.transactions.set.bind(self.data.transactions, tx_hash, tx), - self.data.transactionReceipts.set.bind(self.data.transactionReceipts, tx_hash, receipts[index]) - ); - }); - - async.parallel(requests, (err, result) => { - if (!err) { - self.emit('block', block); - } - callback(err, result); - }); - }); -}; - -BlockchainDouble.prototype.popBlock = function(callback) { - var self = this; - - this.data.blocks.last(function(err, block) { - if (err) return callback(err); - if (block == null) return callback(null, null); - - var requests = []; - var blockHash = to.hex(block.hash()); - - block.transactions.forEach(function(tx, index) { - var tx_hash = to.hex(tx.hash()); - - requests.push( - self.data.transactions.del.bind(self.data.transactions, tx_hash), - self.data.transactionReceipts.del.bind(self.data.transactionReceipts, tx_hash) - ); - }); - - requests.push( - self.data.blockLogs.pop.bind(self.data.blockLogs), - self.data.blockHashes.del.bind(self.data.blockHashes, blockHash), - self.data.blocks.pop.bind(self.data.blocks) // Do this one last in case anything relies on it. - ); - - async.series(requests, function(err) { - if (err) return callback(err); - - // Set the root to the last available, which will "roll back" to the previous - // moment in time. Note that all the old data is still in the db, but it's now just junk data. - self.data.blocks.last(function(err, newLastBlock) { - if (err) return callback(err); - self.stateTrie.root = newLastBlock.header.stateRoot; - // Remember: Return block we popped off. - callback(null, block); - }); - }); - }); -}; - -BlockchainDouble.prototype.clearPendingTransactions = function() { - this.pending_transactions = []; -}; - -BlockchainDouble.prototype.putAccount = function(account, address, callback) { - var self = this; - - address = utils.toBuffer(address); - - this.vm.stateManager.putAccount(address, account, function(err) { - if (err) return callback(err); - - self.vm.stateManager.cache.flush(callback); - }); -}; - -/** - * createBlock - * - * Create a new block, where the parent's block is either the latest block - * on the chain or the parent block passed in. - * - * @param {Block} parent The block meant to be the parent block (optional) - * @param {Function} callback Callback function called after block is created - * @return Block The block created. - */ -BlockchainDouble.prototype.createBlock = function(parent, callback) { - var self = this; - - if (typeof parent == "function") { - callback = parent; - parent = null; - } - - var block = new Block(); - - function getParent(callback) { - if (parent) { - return callback(null, parent); - } else { - self.latestBlock(callback); - } - }; - - getParent(function(err, parent) { - if (err) return callback(err); - - var parentNumber = parent != null ? to.number(parent.header.number) : -1; - - block.header.gasLimit = self.blockGasLimit; - - // Ensure we have the right block number for the VM. - block.header.number = to.hex(parentNumber + 1); - - // Set the timestamp before processing txs - block.header.timestamp = to.hex(self.currentTime()); - - if (parent != null) { - block.header.parentHash = to.hex(parent.hash()); - } - - callback(null, block); - }); -}; - -BlockchainDouble.prototype.getQueuedNonce = function(address, callback) { - var nonce = null; - - this.pending_transactions.forEach(function(tx) { - //tx.from and address are buffers, so cannot simply do - //tx.from==address - if (to.hex(tx.from) != to.hex(address)) return; - - var pending_nonce = to.number(tx.nonce); - //If this is the first queued nonce for this address we found, - //or it's higher than the previous highest, note it. - if (nonce===null || pending_nonce > nonce) { - nonce = pending_nonce; - } - }); - - //If we found a queued transaction nonce, return one higher - //than the highest we found - if (nonce!=null) return callback(null, nonce+1); - - this.stateTrie.get(address, function(err, val) { - if (err) return callback(err); - - var account = new Account(val); - callback(null, account.nonce); - }); -}; - -BlockchainDouble.prototype.queueTransaction = function(tx) { - this.pending_transactions.push(tx); -}; - -BlockchainDouble.prototype.sortByPriceAndNonce = function() { - // Sorts transactions like I believe geth does. - // See the description of 'SortByPriceAndNonce' at - // https://github.com/ethereum/go-ethereum/blob/290e851f57f5d27a1d5f0f7ad784c836e017c337/core/types/transaction.go - var self = this; - var sortedByNonce = {}; - - self.pending_transactions.forEach((tx) => { - if (!sortedByNonce[to.hex(tx.from)]){ - sortedByNonce[to.hex(tx.from)] = [tx]; - } else { - sortedByNonce[to.hex(tx.from)].push(tx); - } - }); - - var priceSort = function(a,b){ - return parseInt(to.hex(b.gasPrice),16)-parseInt(to.hex(a.gasPrice),16); - } - var nonceSort = function(a,b){ - return parseInt(to.hex(a.nonce),16) - parseInt(to.hex(b.nonce),16) - } - - // Now sort each address by nonce - Object.keys(sortedByNonce).forEach((address) => { - sortedByNonce[address].sort(nonceSort) - }) - - // Initialise a heap, sorted by price, for the head transaction from each account. - var heap = new Heap(priceSort); - Object.keys(sortedByNonce).forEach((address) => { - heap.push(sortedByNonce[address].shift()); - }) - - // Now reorder our transactions. Compare the next transactions from each account, and choose - // the one with the highest gas price. - const sorted_transactions = []; - while (heap.size()>0){ - const best = heap.pop(); - let address = to.hex(best.from) - if (sortedByNonce[address].length>0){ - //Push on the next transaction from this account - heap.push(sortedByNonce[address].shift()); - } - sorted_transactions.push(best); - } - self.pending_transactions = sorted_transactions; -}; - -BlockchainDouble.prototype.processCall = function(tx, blockNumber, callback) { - var self = this; - var startingStateRoot; - - var cleanUpAndReturn = function (err, result, changeRoot) { - self.vm.stateManager.revert(function (e) { - // For defaultBlock, undo state root changes - if (changeRoot){ - self.stateTrie.root = startingStateRoot; - } - callback(err || e, result); - }); - }; - - var runCall = function(tx, changeRoot, err, block){ - if (err) return callback(err); - - // For defaultBlock, use that block's root - if (changeRoot){ - startingStateRoot = self.stateTrie.root; - self.stateTrie.root = block.header.stateRoot; - } - - // create a fake block with this fake transaction - self.createBlock(block, function(err, block) { - block.transactions.push(tx); - - // We checkpoint here for speed. We want all state trie reads/writes to happen in memory, - // and the final output be flushed to the database at the end of transaction processing. - self.vm.stateManager.checkpoint(); - - var runArgs = { - tx: tx, - block: block, - skipBalance: true, - skipNonce: true - }; - - self.vm.runTx(runArgs, function (vmerr, result) { - // This is a check that has been in there for awhile. I'm unsure if it's required, but it can't hurt. - if (vmerr && vmerr instanceof Error == false) { - vmerr = new Error("VM error: " + vmerr); - } - - // If we're given an error back directly, it's worse than a runtime error. Expose it and get out. - if (vmerr) return cleanUpAndReturn(vmerr); - - // If no error, check for a runtime error. This can return null if no runtime error. - vmerr = RuntimeError.fromResults([tx], { results: [result] }); - - cleanUpAndReturn(vmerr, result, changeRoot); - }); - }); - }; - - // Delegate block selection - (blockNumber === 'latest') - ? self.latestBlock(runCall.bind(null, tx, false)) - : self.getBlock(blockNumber, runCall.bind(null, tx, true)); -} - -/** - * processBlock - * - * Process the passed in block and included transactions - * - * @param {Block} block block to process - * @param {Boolean} commit Whether or not changes should be committed to the state trie and the block appended to the end of the chain. - * @param {Function} callback Callback function when transaction processing is completed. - * @return [type] [description] - */ -BlockchainDouble.prototype.processBlock = function(block, commit, callback) { - var self = this; - - if (typeof commit == "function") { - callback = commit; - commit = true; - } - - var currentStateRoot = self.stateTrie.root; - - // We checkpoint here for speed. We want all state trie reads/writes to happen in memory, - // and the final output be flushed to the database at the end of transaction processing. - self.vm.stateManager.checkpoint(); - - var cleanup = function(err) { - self.vm.stateManager.revert(function(e) { - callback(err || e); - }); - }; - - self.vm.runBlock({ - block: block, - generate: true, - }, function(vmerr, results) { - // This is a check that has been in there for awhile. I'm unsure if it's required, but it can't hurt. - if (vmerr && vmerr instanceof Error == false) { - vmerr = new Error("VM error: " + vmerr); - } - - // If we're given an error back directly, it's worse than a runtime error. Expose it and get out. - if (vmerr) return cleanup(vmerr); - - // If no error, check for a runtime error. This can return null if no runtime error. - vmerr = RuntimeError.fromResults(block.transactions, results); - - // Note, even if we have an error, some transactions may still have succeeded. - // Process their logs if so, returning the error at the end. - - var logs = []; - var receipts = []; - - var totalBlockGasUsage = 0; - - results.results.forEach(function(result) { - totalBlockGasUsage += to.number(result.gasUsed); - }); - - block.header.gasUsed = utils.toBuffer(to.hex(totalBlockGasUsage)); - - for (var v = 0; v < results.receipts.length; v++) { - var result = results.results[v]; - var receipt = results.receipts[v]; - var tx = block.transactions[v]; - var tx_hash = tx.hash(); - var tx_logs = []; - - // Only process the transaction's logs if it didn't error. - if (result.vm.exception == 1) { - for (var i = 0; i < receipt.logs.length; i++) { - var log = receipt.logs[i]; - var address = to.hex(log[0]); - var topics = [] - - for (var j = 0; j < log[1].length; j++) { - topics.push(to.hex(log[1][j])); - } - - var data = to.hex(log[2]); - - var log = new Log({ - logIndex: to.rpcQuantityHexString(i), - transactionIndex: to.rpcQuantityHexString(v), - transactionHash: tx_hash, - block: block, - address: address, - data: data, - topics: topics, - type: "mined" - }); - - logs.push(log); - tx_logs.push(log); - } - } - - let rcpt = new Receipt(tx, block, tx_logs, result.gasUsed.toArrayLike(Buffer), receipt.gasUsed, result.createdAddress, receipt.status, to.hex(result.bloom.bitvector)); - receipts.push(rcpt); - } - - function commmitIfNeeded(cb) { - if (commit === true) { - self.vm.stateManager.commit(function(e) { - if (e) return cleanup(e); - - // Put that block on the end the chain - self.putBlock(block, logs, receipts, cb); - }); - } else { - self.vm.stateManager.revert(cb); - } - } - - commmitIfNeeded(function(e) { - if (e) return callback(e); - // Note we return the vm err here too, if it exists. - callback(vmerr, block.transactions, results); - }); - }); -}; - -/** - * processNextBlock - * - * Process the next block like a normal blockchain, pulling from the list of - * pending transactions. - * - * @param {number} timestamp at which the block is mined - * @param {Function} callback Callback when transaction processing is finished. - * @return [type] [description] - */ -BlockchainDouble.prototype.processNextBlock = function(timestamp, callback) { - var self = this; - - if (typeof timestamp === 'function') { - callback = timestamp; - timestamp = undefined; - } - - self.sortByPriceAndNonce(); - - var successfullyAddedTransactions = []; - - // Grab only the transactions that can fit within the block - var currentTransactions = []; - var totalGasLimit = 0; - var maxGasLimit = to.number(self.blockGasLimit); - - while (self.pending_transactions.length > 0) { - var tx = self.pending_transactions[0]; - var gasLimit = to.number(tx.gasLimit); - - if (totalGasLimit + gasLimit <= maxGasLimit) { - totalGasLimit += gasLimit; - self.pending_transactions.shift(); - currentTransactions.push(tx); - } else { - // Next one won't fit. Break. - break; - } - } - - // Remember, we ensured transactions had a valid gas limit when they were queued (in the state manager). - // If we run into a case where we can't process any because one is higher than the gas limit, - // then it's a serious issue. This should never happen, but let's check anyway. - if (currentTransactions.length == 0 && self.pending_transactions.length > 0) { - // Error like geth. - return callback("Unexpected error condition: next transaction exceeds block gas limit") - } - - // Create a new block meant to be the end of the chain - this.createBlock(function(err, block) { - if (err) return callback(err); - - //Overwrite block timestamp - if (timestamp) { - self.data.blocks.last(function(err, last) { - if (last && to.number(last.header.timestamp) > timestamp) { - self.logger.log("Waring: Setting the block timestamp (" + timestamp + ") that is earlier than the parent block one."); - } - }); - block.header.timestamp = to.hex(timestamp); - self.setTime(new Date(timestamp * 1000)); - } - // Add transactions to the block. - Array.prototype.push.apply(block.transactions, currentTransactions); - - // Process the block, committing the block to the chain - self.processBlock(block, true, callback); - }); -}; - -/** - * processTransactionTrace - * - * Run a previously-run transaction in the same state in which it occurred at the time it was run. - * This will return the vm-level trace output for debugging purposes. - * - * Strategy: - * - * 1. Find block where transaction occurred - * 2. Set state root of that block - * 3. Rerun every transaction in that block prior to and including the requested transaction - * 4. Reset state root back to original - * 5. Send trace results back. - * - * @param {[type]} tx [description] - * @param {Function} callback [description] - * @return [type] [description] - */ -BlockchainDouble.prototype.processTransactionTrace = function(hash, params, callback) { - var self = this; - var target_hash = to.hex(hash); - var tx_hash_currently_processing = ""; - var tx_currently_processing = null; - - var storageStack = { - currentDepth: -1, - stack: [] - } - - var returnVal = { - gas: 0, - returnValue: "", - structLogs: [] - }; - - function step_listener(event, next) { - // See these docs: - // https://github.com/ethereum/go-ethereum/wiki/Management-APIs - - var gasLeft = to.number(event.gasLeft); - var totalGasUsedAfterThisStep = to.number(tx_currently_processing.gasLimit) - gasLeft; - var gasUsedThisStep = totalGasUsedAfterThisStep - returnVal.gas; - returnVal.gas += gasUsedThisStep; - - var isMemoryEnabled = !params.disableMemory; - var memory = null; - if (isMemoryEnabled) { - // Get memory and break it up into 32-byte words. - // Note we may possibly have to pad the final word. - memory = (Buffer.from(event.memory)).toString("hex"); - memory = memory.match(/.{1,64}/g) || []; - - if (memory.length > 0) { - var lastItem = memory[memory.length - 1]; - if (lastItem.length < 64) { - memory[memory.length - 1] = lastItem + new Array(64 - lastItem.length + 1).join("0"); - } - } - } - - var stack = params.disableStack ? null : event.stack.map(function(item) { - return to.rpcDataHexString(item, 64).replace('0x',''); // non-0x prefixed. - }); - - var structLog = { - depth: event.depth, - error: "", - gas: gasLeft, - gasCost: gasUsedThisStep, - memory, - op: event.opcode.name, - pc: event.pc, - stack, - storage: null - } - - if (params.disableStorage) { - returnVal.structLogs.push(structLog); - next(); - } else { - structLog = self.processStorageTrace(structLog, storageStack, event, function(err, structLog) { - if (err) return next(err) - returnVal.structLogs.push(structLog); - next() - }); - } - } - - function beforeTx_listener(tx) { - tx_currently_processing = tx; - tx_hash_currently_processing = to.hex(tx.hash()); - - if (tx_hash_currently_processing == target_hash) { - self.vm.on("step", step_listener); - } - } - - // afterTx_listener cleans up everything. - function afterTx_listener() { - if (tx_hash_currently_processing == target_hash) { - self.vm.removeListener("step", step_listener); - self.vm.removeListener("beforeTx", beforeTx_listener); - self.vm.removeListener("afterTx", afterTx_listener); - } - } - - // Listen to beforeTx and afterTx so we know when our target transaction - // is processing. These events will add the vent listener for getting the trace data. - self.vm.on("beforeTx", beforeTx_listener); - self.vm.on("afterTx", afterTx_listener); - - // #1 - get block via transaction receipt - this.getTransactionReceipt(target_hash, function(err, receipt) { - if (err) return callback(err); - - if (!receipt) { - return callback(new Error("Unknown transaction " + target_hash)); - } - - var targetBlock = receipt.block; - - // Get the parent of the target block - self.getBlock(targetBlock.header.parentHash, function(err, parent) { - if (err) return callback(err); - - var startingStateRoot = self.stateTrie.root; - - // #2 - Set state root of original block - self.stateTrie.root = parent.header.stateRoot; - - // Prepare the "next" block with necessary transactions - self.createBlock(parent, function(err, block) { - if (err) return callback(err); - - for (var i = 0; i < targetBlock.transactions.length; i++) { - var tx = targetBlock.transactions[i]; - block.transactions.push(tx) - - // After including the target transaction, that's all we need to do. - if (to.hex(tx.hash()) == target_hash) { - break; - } - } - - // #3 - Process the block without committing the data. - self.processBlock(block, false, function(err, transactions, results) { - // Ignore runtime errors, or else erroneous transactions can't be traced. - if (err && err.message.indexOf("VM Exception") == 0) { - err = null; - } - - // #4 - reset the state root. - self.stateTrie.root = startingStateRoot; - - // Just to be safe - self.vm.removeListener("beforeTx", beforeTx_listener); - self.vm.removeListener("afterTx", afterTx_listener); - self.vm.removeListener("step", step_listener); - - // #5 - send state results back - callback(err, returnVal); - }); - }); - }); - }); -}; - -BlockchainDouble.prototype.processStorageTrace = function(structLog, storageStack, event, callback) { - var self = this; - var name = event.opcode.name; - - var argsNum = event.opcode.in; - var args = event.stack.slice(-argsNum) - .map((arg) => to.hex(arg)); - - if (storageStack.currentDepth > event.depth) { - storageStack.stack.pop() - } if (storageStack.currentDepth < event.depth) { - storageStack.stack.push({}) - } - - storageStack.currentDepth = event.depth; - - var key; - var value; - switch(name) { - case 'SSTORE': - key = to.rpcDataHexString(args[1], 64).replace('0x','') - value = to.rpcDataHexString(args[0], 64).replace('0x','') - // use Object.assign to prevent future steps from overwriting this step's storage values - structLog.storage = Object.assign({}, storageStack.stack[storageStack.currentDepth]) - - callback(null, structLog) - // assign after callback because this storage change actually takes - // effect _after_ this opcode executes - storageStack.stack[storageStack.currentDepth][key] = value; - break; - case 'SLOAD': - // this one's more fun, we need to get the value the contract is loading from current storage - key = to.rpcDataHexString(args[0], 64).replace('0x','') - - self.vm.stateManager.getContractStorage(event.address, '0x' + key, function(err, result) { - if (err) return callback(err); - - value = to.rpcDataHexString(result, 64).replace('0x','') - storageStack.stack[storageStack.currentDepth][key] = value; - // use Object.assign to prevent future steps from overwriting this step's storage values - structLog.storage = Object.assign({}, storageStack.stack[storageStack.currentDepth]) - callback(null, structLog) - }) - break; - default: - // use Object.assign to prevent future steps from overwriting this step's storage values - structLog.storage = Object.assign({}, storageStack.stack[storageStack.currentDepth]) - callback(null, structLog) - } -}; - -BlockchainDouble.prototype.getAccount = function(address, number, callback) { - var self = this; - - this.getBlock(number, function(err, block) { - if (err) return callback(err); - - var trie = self.stateTrie; - - // Manipulate the state root in place to maintain checkpoints - var currentStateRoot = trie.root; - self.stateTrie.root = block.header.stateRoot; - - trie.get(utils.toBuffer(address), function(err, data) { - // Finally, put the stateRoot back for good - trie.root = currentStateRoot; - - if (err) return callback(err); - - var account = new Account(data); - - account.exists = !!data; - - callback(null, account); - }); - }); -}; - -BlockchainDouble.prototype.getNonce = function(address, number, callback) { - this.getAccount(address, number, function(err, account) { - if (err) return callback(err); - callback(null, account.nonce); - }); -}; - -BlockchainDouble.prototype.getBalance = function(address, number, callback) { - this.getAccount(address, number, function(err, account) { - if (err) return callback(err); - - callback(null, account.balance); - }); -}; - -// Note! Storage values are returned RLP encoded! -BlockchainDouble.prototype.getStorage = function(address, position, number, callback) { - var self = this; - - this.getBlock(number, function(err, block) { - if (err) return callback(err); - - var trie = self.stateTrie; - - // Manipulate the state root in place to maintain checkpoints - var currentStateRoot = trie.root; - self.stateTrie.root = block.header.stateRoot; - - trie.get(utils.toBuffer(address), function(err, data) { - if (err != null) { - // Put the stateRoot back if there's an error - trie.root = currentStateRoot; - return callback(err); - } - - var account = new Account(data); - - trie.root = account.stateRoot; - - trie.get(utils.setLengthLeft(utils.toBuffer(position), 32), function(err, value) { - // Finally, put the stateRoot back for good - trie.root = currentStateRoot; - - if (err != null) { - return callback(err); - } - - callback(null, value); - }); - - }); - }); -} - -BlockchainDouble.prototype.getCode = function(address, number, callback) { - var self = this; - - this.getBlock(number, function(err, block) { - if (err) return callback(err); - - var trie = self.stateTrie; - - // Manipulate the state root in place to maintain checkpoints - var currentStateRoot = trie.root; - self.stateTrie.root = block.header.stateRoot; - - trie.get(utils.toBuffer(address), function(err, data) { - if (err != null) { - // Put the stateRoot back if there's an error - trie.root = currentStateRoot; - return callback(err); - } - - var account = new Account(data); - - account.getCode(trie, function(err, code) { - // Finally, put the stateRoot back for good - trie.root = currentStateRoot; - - if (err) return callback(err); - - callback(null, code); - }); - }); - }); -}; - -BlockchainDouble.prototype.getTransaction = function(hash, callback) { - hash = to.hex(hash); - - this.data.transactions.get(hash, function(err, tx) { - if (err) { - if (err.notFound) { - return callback(null, null); - } else { - return callback(err); - } - } - callback(null, tx); - }); -}; - -BlockchainDouble.prototype.getTransactionReceipt = function(hash, callback) { - hash = to.hex(hash); - - this.data.transactionReceipts.get(hash, function(err, receipt) { - if (err) { - if (err.notFound) { - return callback(null, null); - } else { - return callback(err); - } - } - - callback(err, receipt); - }); -}; - -BlockchainDouble.prototype.getBlockLogs = function(number, callback) { - var self = this; - this.getEffectiveBlockNumber(number, function(err, effective) { - if (err) return callback(err); - self.data.blockLogs.get(effective, callback); - }); -}; - -BlockchainDouble.prototype.getHeight = function(callback) { - this.data.blocks.length(function(err, length) { - if (err) return callback(err); - callback(null, length - 1); - }) -}; - -BlockchainDouble.prototype.currentTime = function() { - return (new Date().getTime() / 1000 | 0) + this.timeAdjustment; -}; - -BlockchainDouble.prototype.increaseTime = function(seconds) { - if (seconds < 0) seconds = 0; - this.timeAdjustment += seconds; - return this.timeAdjustment; -}; - -BlockchainDouble.prototype.setTime = function(date) { - var now = new Date().getTime() / 1000 | 0; - var start = date.getTime() / 1000 | 0; - this.timeAdjustment = start - now; -}; - -BlockchainDouble.prototype.close = function(callback) { - this.data.close(callback); -}; - -module.exports = BlockchainDouble; diff --git a/lib/database.js b/lib/database.js deleted file mode 100644 index ba2472c5f3..0000000000 --- a/lib/database.js +++ /dev/null @@ -1,69 +0,0 @@ -var LevelUpArrayAdapter = require("./database/leveluparrayadapter"); -var LevelUpObjectAdapter = require("./database/levelupobjectadapter"); -var levelup = require('levelup'); -var encode = require('encoding-down') -var filedown = require("./database/filedown"); -var cachedown = require("cachedown"); -var Sublevel = require("level-sublevel"); -var Block = require("ethereumjs-block"); -var txserializer = require("./database/txserializer"); -var blockserializer = require("./database/blockserializer"); -var bufferserializer = require("./database/bufferserializer"); -var BlockLogsSerializer = require("./database/blocklogsserializer"); -var ReceiptSerializer = require("./database/receiptserializer"); -var to = require("./utils/to"); -var utils = require("ethereumjs-util"); -var FakeTransaction = require('ethereumjs-tx/fake.js'); -var tmp = require("tmp"); - -function Database(options) { - this.options = options; -}; - -Database.prototype.initialize = function(callback) { - var self = this; - - function getDir(cb) { - if (self.options.db_path) { - cb(null, self.options.db_path); - } else { - tmp.dir(cb); - } - } - - getDir(function(err, directory) { - if (err) return callback(err); - levelup(self.options.db || encode(cachedown(directory, filedown).maxSize(100)), {valueEncoding: "json"}, finishInitializing); - }); - - function finishInitializing(err, db) { - if (err) return callback(err); - - self.db = db; - - // Blocks, keyed by array index (not necessarily by block number) (0-based) - self.blocks = new LevelUpArrayAdapter("blocks", self.db, blockserializer); - - // Logs triggered in each block, keyed by block id (ids in the blocks array; not necessarily block number) (0-based) - self.blockLogs = new LevelUpArrayAdapter("blockLogs", self.db, new BlockLogsSerializer(self)); - - // Block hashes -> block ids (ids in the blocks array; not necessarily block number) for quick lookup - self.blockHashes = new LevelUpObjectAdapter("blockHashes", self.db); - - // Transaction hash -> transaction objects - self.transactions = new LevelUpObjectAdapter("transactions", self.db, txserializer); - - // Transaction hash -> transaction receipts - self.transactionReceipts = new LevelUpObjectAdapter("transactionReceipts", self.db, new ReceiptSerializer(self)); - - self.trie_db = new LevelUpObjectAdapter("trie_db", self.db, bufferserializer, bufferserializer); - - callback(); - }; -}; - -Database.prototype.close = function(callback) { - callback(); -}; - -module.exports = Database; diff --git a/lib/database/blocklogsserializer.js b/lib/database/blocklogsserializer.js deleted file mode 100644 index 16d58e1d68..0000000000 --- a/lib/database/blocklogsserializer.js +++ /dev/null @@ -1,49 +0,0 @@ -var to = require("../utils/to"); -var Log = require("../utils/log"); -var async = require("async"); - -function BlockLogsSerializer(database) { - this.database = database; -}; - -BlockLogsSerializer.prototype.encode = function(logs, done) { - logs = logs.map(function(log) { - return log.toJSON(); - }); - - done(null, logs); -}; - -BlockLogsSerializer.prototype.decode = function(json, done) { - var self = this; - - if (json.length == 0) { - return done(null, []); - } - - this.database.blockHashes.get(json[0].blockHash, function(err, blockIndex) { - if (err) return done(err); - - self.database.blocks.get(blockIndex, function(err, block) { - if (err) return done(err); - - async.map(json, function(log, finished) { - finished(null, new Log({ - block: block, - logIndex: log.logIndex, - transactionIndex: log.transactionIndex, - transactionHash: log.transactionHash, - address: log.address, - data: log.data, - topics: log.topics, - type: log.type - })); - }, function(err, logs) { - if (err) return done(err); - done(null, logs) - }); - }); - }); -}; - -module.exports = BlockLogsSerializer; diff --git a/lib/database/blockserializer.js b/lib/database/blockserializer.js deleted file mode 100644 index 3a67643538..0000000000 --- a/lib/database/blockserializer.js +++ /dev/null @@ -1,36 +0,0 @@ -var to = require("../utils/to"); -var txserializer = require("./txserializer"); -var async = require("async"); -var Block = require("ethereumjs-block"); - -module.exports = { - encode: function(block, done) { - var encoded = block.toJSON(true); - - async.map(block.transactions, function(tx, finished) { - txserializer.encode(tx, finished); - }, function(err, transactions) { - if (err) return done(err); - encoded.transactions = transactions; - done(null, encoded); - }); - }, - decode: function(json, done) { - var transactions = json.transactions; - json.transactions = []; - - var block = new Block(json); - - async.eachSeries(transactions, function(tx_json, finished) { - txserializer.decode(tx_json, function(err, tx) { - if (err) return finished(err); - block.transactions.push(tx); - finished(); - }); - }, function(err) { - if (err) return done(err); - - done(null, block); - }); - } -} diff --git a/lib/database/bufferserializer.js b/lib/database/bufferserializer.js deleted file mode 100644 index 95e703d48f..0000000000 --- a/lib/database/bufferserializer.js +++ /dev/null @@ -1,12 +0,0 @@ -var utils = require("ethereumjs-util"); -var to = require("../utils/to"); - -module.exports = { - encode: function(val, cb) { - var hex = to.hex(val); - cb(null, hex); - }, - decode: function(json, cb) { - cb(null, utils.toBuffer(json)) - } -}; diff --git a/lib/database/filedown.js b/lib/database/filedown.js deleted file mode 100644 index 0c262ed461..0000000000 --- a/lib/database/filedown.js +++ /dev/null @@ -1,66 +0,0 @@ -var util = require('util'); -var AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN; -var async = require("async"); -var fs = require("fs"); -var path = require("path"); - -util.inherits(FileDown, AbstractLevelDOWN) - -function FileDown (location) { - this.location = location; - AbstractLevelDOWN.call(this, location) -} - -FileDown.prototype._open = function (options, callback) { - var self = this; - callback(null, self); -} - -FileDown.prototype._put = function (key, value, options, callback) { - var self = this; - fs.writeFile(path.join(this.location, key), value, "utf8", callback); -} - -FileDown.prototype._get = function (key, options, callback) { - fs.readFile(path.join(this.location, key), "utf8", function(err, data) { - if (err) { - return callback(new Error("NotFound")); - } - callback(null, data); - }); -} - -FileDown.prototype._del = function (key, options, callback) { - fs.unlink(path.join(this.location, key), function(err) { - // Ignore when we try to delete a file that doesn't exist. - // I'm not sure why this happens. Worth looking into. - if (err) { - if (err.message.indexOf("ENOENT") >= 0) { - return callback(); - } else { - return callback(err); - } - } - callback(); - }); -} - -FileDown.prototype._batch = function(array, options, callback) { - var self = this; - async.each(array, function(item, finished) { - if (item.type == "put") { - self.put(item.key, item.value, options, finished); - } else if (item.type == "del") { - self.del(item.key, options, finished); - } else { - finished(new Error("Unknown batch type", item.type)); - } - }, function(err) { - if (err) return callback(err); - callback(); - }); -} - -module.exports = function(location) { - return new FileDown(location); -}; diff --git a/lib/database/leveluparrayadapter.js b/lib/database/leveluparrayadapter.js deleted file mode 100644 index a8781e5279..0000000000 --- a/lib/database/leveluparrayadapter.js +++ /dev/null @@ -1,108 +0,0 @@ -var Sublevel = require("level-sublevel"); - -// Level up adapter that looks like an array. Doesn't support inserts. - -function LevelUpArrayAdapter(name, db, serializer) { - this.db = Sublevel(db); - this.db = this.db.sublevel(name); - this.name = name; - this.serializer = serializer || { - encode: function(val, callback) { callback(null, val); }, - decode: function(val, callback) { callback(null, val); } - }; -}; - -LevelUpArrayAdapter.prototype.length = function(callback) { - this.db.get("length", function(err, result) { - if (err) { - if (err.notFound) { - return callback(null, 0); - } else { - return callback(err); - } - } - - callback(null, result); - }); -}; - -LevelUpArrayAdapter.prototype._get = function(key, callback) { - var self = this; - this.db.get(key, function(err, val) { - if (err) return callback(err); - self.serializer.decode(val, callback); - }); -}; - -LevelUpArrayAdapter.prototype._put = function(key, value, callback) { - var self = this; - this.serializer.encode(value, function(err, encoded) { - if (err) return callback(err); - self.db.put(key, encoded, callback); - }); -}; - -LevelUpArrayAdapter.prototype.get = function(index, callback) { - var self = this; - - this.length(function(err, length) { - if (err) return callback(err); - if (index >= length) { - return callback(new Error("LevelUpArrayAdapter named '" + self.name + "' index out of range: index " + index + "; length: " + length)); - } - self._get(index, callback); - }); -}; - -LevelUpArrayAdapter.prototype.push = function(val, callback) { - var self = this; - this.length(function(err, length) { - if (err) return callback(err); - - // TODO: Do this in atomic batch. - self._put(length + "", val, function(err) { - if (err) return callback(err); - self.db.put("length", length + 1, callback); - }); - }); -}; - -LevelUpArrayAdapter.prototype.pop = function(callback) { - var self = this; - - this.length(function(err, length) { - if (err) return callback(err); - - var newLength = length - 1; - - // TODO: Do this in atomic batch. - self._get(newLength + "", function(err, val) { - if (err) return callback(err); - self.db.del(newLength + "", function(err) { - if (err) return callback(err); - self.db.put("length", newLength, function(err) { - if (err) return callback(err); - - callback(null, val); - }); - }); - }); - }); -}; - -LevelUpArrayAdapter.prototype.last = function(callback) { - var self = this; - this.length(function(err, length) { - if (err) return callback(err); - - if (length == 0) return callback(null, null); - - self._get((length - 1) + "", callback); - }); -}; - -LevelUpArrayAdapter.prototype.first = function(callback) { - this._get("0", callback); -}; - -module.exports = LevelUpArrayAdapter; diff --git a/lib/database/levelupobjectadapter.js b/lib/database/levelupobjectadapter.js deleted file mode 100644 index 8175170674..0000000000 --- a/lib/database/levelupobjectadapter.js +++ /dev/null @@ -1,93 +0,0 @@ -var Sublevel = require("level-sublevel"); -var async = require("async"); - -function LevelUpObjectAdapter(name, db, valueserializer, keyserializer, options) { - this.db = Sublevel(db, options); - this.db = this.db.sublevel(name); - this.name = name; - this.valueserializer = valueserializer || { - encode: function(val, callback) { callback(null, val); }, - decode: function(val, callback) { callback(null, val); } - }; - this.keyserializer = keyserializer || { - encode: function(val, callback) { callback(null, val); }, - decode: function(val, callback) { callback(null, val); } - }; -}; - -LevelUpObjectAdapter.prototype.get = function(key, options, callback) { - var self = this; - - if (typeof options == "function") { - callback = options; - options = {}; - } - - this.keyserializer.encode(key, function(err, encodedKey) { - if (err) return callback(err); - - self.db.get(encodedKey, function(err, val) { - if (err) return callback(err); - - self.valueserializer.decode(val, function(err, decodedValue) { - if (err) return callback(err); - - callback(null, decodedValue); - }); - }); - }); -}; - -LevelUpObjectAdapter.prototype.put = function(key, value, options, callback) { - var self = this; - - if (typeof options == "function") { - callback = options; - options = {}; - } - - this.keyserializer.encode(key, function(err, encodedKey) { - if (err) return callback(err); - - self.valueserializer.encode(value, function(err, encoded) { - if (err) return callback(err); - - self.db.put(encodedKey, encoded, callback); - }); - }); -}; - -LevelUpObjectAdapter.prototype.set = LevelUpObjectAdapter.prototype.put; - -LevelUpObjectAdapter.prototype.del = function(key, callback) { - var self = this; - - this.keyserializer.encode(key, function(err, encodedKey) { - if (err) return callback(err); - - self.db.del(encodedKey, callback); - }); -} - -LevelUpObjectAdapter.prototype.batch = function(array, options, callback) { - var self = this; - - async.each(array, function(item, finished) { - if (item.type == "put") { - self.put(item.key, item.value, options, finished); - } else if (item.type == "del") { - self.del(item.key, finished); - } else { - finished(new Error("Unknown batch type", item.type)); - } - }, function(err) { - if (err) return callback(err); - callback(); - }); -}; - -LevelUpObjectAdapter.prototype.isOpen = function() { - return true; -} - -module.exports = LevelUpObjectAdapter; diff --git a/lib/database/levelupvalueadapter.js b/lib/database/levelupvalueadapter.js deleted file mode 100644 index 6c59012d76..0000000000 --- a/lib/database/levelupvalueadapter.js +++ /dev/null @@ -1,44 +0,0 @@ -// Warning: Wrote this because I wanted it, then didn't need it. -// May come in handy later. You've been warned. This might be bad/dead code. -var Sublevel = require("level-sublevel"); - -function LevelUpValueAdapter(name, db, serializer) { - this.db = Sublevel(db); - this.db = this.db.sublevel(name); - this.name = name; - this.serializer = serializer || { - encode: function(val, callback) { callback(null, val); }, - decode: function(val, callback) { callback(null, val); } - }; - this.value_key = "value"; -}; - -LevelUpValueAdapter.prototype.get = function(callback) { - var self = this; - - this.db.get(this.value_key, function(err, val) { - if (err) { - if (err.notFound) { - return callback(null, null); - } else { - return callback(err); - } - } - - self.serializer.decode(val, callback); - }); -}; - -LevelUpValueAdapter.prototype.set = function(value, callback) { - var self = this; - this.serializer.encode(value, function(err, encoded) { - if (err) return callback(err); - self.db.put(self.value_key, encoded, callback); - }); -}; - -LevelUpValueAdapter.prototype.del = function(callback) { - this.db.del(this.value_key, callback); -} - -module.exports = LevelUpValueAdapter; diff --git a/lib/database/receiptserializer.js b/lib/database/receiptserializer.js deleted file mode 100644 index 78e43c4199..0000000000 --- a/lib/database/receiptserializer.js +++ /dev/null @@ -1,34 +0,0 @@ -var to = require("../utils/to"); -var Receipt = require("../utils/receipt"); -var async = require("async"); - -function ReceiptSerializer(database) { - this.database = database; -}; - -ReceiptSerializer.prototype.encode = function(receipt, done) { - done(null, receipt.toJSON()); -}; - -ReceiptSerializer.prototype.decode = function(json, done) { - var self = this; - - this.database.transactions.get(json.transactionHash, function(err, tx) { - if (err) return done(err); - - self.database.blockHashes.get(json.blockHash, function(err, blockIndex) { - if (err) return done(err); - - async.parallel({ - block: self.database.blocks.get.bind(self.database.blocks, blockIndex), - logs: self.database.blockLogs.get.bind(self.database.blockLogs, blockIndex) - }, function(err, result) { - if (err) return done(err); - - done(null, new Receipt(tx, result.block, result.logs, json.gasUsed, json.cumulativeGasUsed, json.contractAddress, json.status, json.logsBloom)); - }); - }); - }); -}; - -module.exports = ReceiptSerializer; diff --git a/lib/database/txserializer.js b/lib/database/txserializer.js deleted file mode 100644 index ec49d7f14c..0000000000 --- a/lib/database/txserializer.js +++ /dev/null @@ -1,38 +0,0 @@ -var to = require("../utils/to"); -var utils = require("ethereumjs-util"); -var FakeTransaction = require("ethereumjs-tx/fake.js") - -module.exports = { - encode: function(tx, done) { - var encoded = tx.toJSON(true); - - encoded.from = to.hex(tx.from); - encoded.hash = to.hex(tx.hash()); - - done(null, encoded); - }, - decode: function(json, done) { - // TODO: We can't use txhelper here because there are two - // JSON serialization types: ethereumjs-tx, and web3. - // Here we deserialize from ethereumjs-tx because it's - // closer to the metal, so to speak. - var tx = new FakeTransaction({ - nonce: utils.toBuffer(json.nonce), - value: utils.toBuffer(json.value), - to: utils.toBuffer(json.to), - from: utils.toBuffer(json.from), - gasLimit: utils.toBuffer(json.gasLimit), - gasPrice: utils.toBuffer(json.gasPrice), - data: utils.toBuffer(json.data), - v: utils.toBuffer(json.v), - r: utils.toBuffer(json.r), - s: utils.toBuffer(json.s) - }); - - // if (to.hex(tx.hash()) != json.hash) { - // return done(new Error("DB consistency check: Decoded transaction hash didn't match encoded hash. Expected: " + json.hash + "; actual: " + to.hex(tx.hash()))); - // } - - done(null, tx); - } -} diff --git a/lib/httpServer.js b/lib/httpServer.js deleted file mode 100644 index 78e79f49e3..0000000000 --- a/lib/httpServer.js +++ /dev/null @@ -1,78 +0,0 @@ -var http = require("http"); - -module.exports = function (provider, logger) { - var server = http.createServer(function (request, response) { - - var headers = request.headers; - var method = request.method; - var url = request.url; - var body = []; - - request.on('error', function (err) { - // console.error(err); - }).on('data', function (chunk) { - body.push(chunk); - }).on('end', function () { - body = Buffer.concat(body).toString(); - // At this point, we have the headers, method, url and body, and can now - // do whatever we need to in order to respond to this request. - - var headers = { - "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, User-Agent", - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "*" - }; - - switch (method) { - case "OPTIONS": - headers[ "Content-Type" ] = "text/plain" - response.writeHead(200, headers); - response.end(""); - break; - case "POST": - //console.log("Request coming in:", body); - - var payload; - try { - payload = JSON.parse(body); - } catch (e) { - headers[ "Content-Type" ] = "text/plain"; - response.writeHead(400, headers); - response.end("400 Bad Request"); - return; - } - - // Log messages that come into the TestRPC via http - if (payload instanceof Array) { - // Batch request - for (var i = 0; i < payload.length; i++) { - var item = payload[ i ]; - logger.log(item.method); - } - } else { - logger.log(payload.method); - } - - provider.send(payload, function (err, result) { - headers[ "Content-Type" ] = "application/json"; - response.writeHead(200, headers); - response.end(JSON.stringify(result)); - }); - - break; - default: - response.writeHead(400, { - "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, User-Agent", - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "*", - "Content-Type": "text/plain" - }); - response.end("400 Bad Request"); - break; - } - }); - }); - - server.ganacheProvider = provider; - return server; -}; diff --git a/lib/provider.js b/lib/provider.js deleted file mode 100644 index 9780d10ad6..0000000000 --- a/lib/provider.js +++ /dev/null @@ -1,248 +0,0 @@ -// make sourcemaps work! -require('source-map-support/register') - -let ProviderEngine = require("web3-provider-engine"); -let SubscriptionSubprovider = require('web3-provider-engine/subproviders/subscriptions'); - -let RequestFunnel = require('./subproviders/requestfunnel'); -let DelayedBlockFilter = require("./subproviders/delayedblockfilter"); -let GethDefaults = require("./subproviders/gethdefaults"); -let GethApiDouble = require('./subproviders/geth_api_double'); - -let BlockTracker = require('./block_tracker'); - -let RuntimeError = require("./utils/runtimeerror"); -let EventEmitter = require('events'); - -let _ = require('lodash') - -function Provider(options) { - const self = this; - EventEmitter.call(this); - - this.options = options = self._applyDefaultOptions(options || {}) - - let gethApiDouble = new GethApiDouble(options, this); - - this.engine = new ProviderEngine({ - blockTracker: new BlockTracker({ blockchain: gethApiDouble.state.blockchain }) - }); - - let subscriptionSubprovider = new SubscriptionSubprovider(); - - this.engine.manager = gethApiDouble; - this.engine.addProvider(new RequestFunnel()); - this.engine.addProvider(new DelayedBlockFilter()); - this.engine.addProvider(subscriptionSubprovider); - this.engine.addProvider(new GethDefaults()); - this.engine.addProvider(gethApiDouble); - - this.engine.setMaxListeners(100); - this.engine.start(); - - this.manager = gethApiDouble; - this.sendAsync = this.send.bind(this); - this.send = this.send.bind(this); - this.close = this.close.bind(this); - this._queueRequest = this._queueRequest.bind(this); - this._processRequestQueue = this._processRequestQueue.bind(this); - - subscriptionSubprovider.on('data', function(err, notification) { - self.emit('data', err, notification); - }); -}; - -const defaultOptions = { - vmErrorsOnRPCResponse: true, - verbose: false, - asyncRequestProcessing: false, - logger: { - log: function() {} - } -} - -Provider.prototype = Object.create(EventEmitter.prototype); -Provider.prototype.constructor = Provider; - -Provider.prototype._applyDefaultOptions = function(options) { - return _.merge({}, defaultOptions, options) -} - -Provider.prototype.send = function(payload, callback) { - if (typeof callback != 'function') { - throw new Error("No callback provided to provider's send function. As of web3 1.0, provider.send is no longer synchronous and must be passed a callback as its final argument."); - } - - let self = this; - - let externalize = function(payload) { - return _.cloneDeep(payload) - }; - - if (Array.isArray(payload)) { - payload = payload.map(externalize) - } else { - payload = externalize(payload); - } - - let intermediary = function(err, result) { - // clone result so that we can mutate the response without worrying about - // that messing up assumptions the calling logic might have about us - // mutating things - result = _.cloneDeep(result) - let response; - if (Array.isArray(result)) { - response = [] - for (let i = 0; i < result.length; i++) { - response.push(self.reportErrorInResponse(payload[i], err, result[i])) - } - } else { - response = self.reportErrorInResponse(payload, err, result); - } - - if (self.options.verbose) { - self.options.logger.log(" < " + JSON.stringify(response, null, 2).split("\n").join("\n < ")); - } - callback(response.error ? err : null, response); - }; - - if (self.options.verbose) { - self.options.logger.log(" > " + JSON.stringify(payload, null, 2).split("\n").join("\n > ")); - } - - if (self.options.asyncRequestProcessing) { - self.engine.sendAsync(payload, intermediary); - } else { - self._queueRequest(payload, intermediary); - } -}; - -Provider.prototype.close = function(callback) { - // This is a little gross reaching, but... - this.manager.state.blockchain.close(callback); - this.engine.stop() -}; - -Provider.prototype._queueRequest = function(payload, intermediary) { - if (!this._requestQueue) { - this._requestQueue = [] - } - - this._requestQueue.push({ - payload: payload, - callback: intermediary - }); - - setImmediate(this._processRequestQueue) -} - -Provider.prototype._processRequestQueue = function() { - const self = this; - - if (self._requestInProgress) return - - self._requestInProgress = true - - let args = self._requestQueue.shift() - - if (args) { - self.engine.sendAsync(args.payload, (err, result) => { - if (self._requestQueue.length > 0) { - setImmediate(self._processRequestQueue) - } - args.callback(err, result) - self._requestInProgress = false; - }) - } else { - // still need to free the lock - self._requestInProgress = false; - - if (self._requestQueue.length > 0) { - setImmediate(self._processRequestQueue) - } - } -} - -Provider.prototype.cleanUpErrorObject = function(err, response) { - // Our response should already have an error field at this point, if it - // doesn't, this was likely intentional. If not, this is the wrong place to - // fix that problem. - if (!err || !response.error) { - return response - } - - let errorObject = { - error: { - data: {} - }, - } - - if (err.message) { - // clean up the error reporting done by the provider engine so the error message isn't lost in the stack trace noise - errorObject.error.message = err.message; - errorObject.error.data.stack = err.stack; - errorObject.error.data.name = err.name; - } else if (!response.error) { - errorObject.error = { - message: err.toString() - } - } - - return _.merge(response, errorObject) -} - -// helper list of RPC methods which execute code and respond with a transaction hash as their result -let transactionMethods = [ - 'eth_sendTransaction', - 'eth_sendRawTransaction', - 'personal_sendTransaction' -]; - -Provider.prototype._isTransactionRequest = function(request) { - return transactionMethods.indexOf(request.method) != -1; -} - -Provider.prototype.reportErrorInResponse = function(request, err, response) { - const self = this; - - if (!err) return response; - - // TODO: for next major release: move reporting of tx hash on error to error - // field to prevent poorly-written clients which assume that the existence of - // the "result" field implies no errors from breaking. - if (self._isTransactionRequest(request)) { - if (err instanceof RuntimeError) { - // Make sure we always return the transaction hash on failed transactions so - // the caller can get their tx receipt. This breaks JSONRPC 2.0, but it's how - // we've always done it. - response.result = err.hashes[0] - - if (self.options.vmErrorsOnRPCResponse) { - if(!response.error.data) { - response.error.data = {} - } - response.error.data[err.hashes[0]] = err.results[err.hashes[0]] - } else { - delete response.error - } - } - } - - if (request.method === 'eth_call') { - if (err instanceof RuntimeError) { - if (self.options.vmErrorsOnRPCResponse) { - if(!response.error.data) { - response.error.data = {} - } - response.error.data[err.hashes[0]] = err.results[err.hashes[0]] - } else { - response.result = err.results[err.hashes[0]].return || '0x' - delete response.error - } - } - } - - return self.cleanUpErrorObject(err, response) -} - -module.exports = Provider; diff --git a/lib/server.js b/lib/server.js deleted file mode 100644 index ea07235d00..0000000000 --- a/lib/server.js +++ /dev/null @@ -1,85 +0,0 @@ -// make sourcemaps work! -require('source-map-support/register') - -var Provider = require("./provider"); -var webSocketServer = require("./webSocketServer"); -var httpServer = require("./httpServer"); -var _ = require("lodash"); - -module.exports = { - create: function(options) { - options = _applyDefaultOptions(options || {}) - - var logger = options.logger; - var provider = new Provider(options); - - var server = httpServer(provider, logger); - - let connectionCounter = 0; - const connections = {}; - server.on('connection', conn => { - let key = connectionCounter++; - connections[key] = conn; - conn.on('close', () => delete connections[key]) - }); - - var oldListen = server.listen; - - server.listen = function() { - var args = Array.prototype.slice.call(arguments); - var callback = function() {}; - if (args.length > 0) { - var last = args[args.length - 1]; - if (typeof last == "function") { - callback = args.pop(); - } - } - - var intermediary = function(err) { - if (err) return callback(err); - server.provider.manager.waitForInitialization(callback); - }; - - args.push(intermediary); - - oldListen.apply(server, args); - } - - server.provider = provider; - - var wss = null; - - if (options.ws) { - wss = webSocketServer(server, provider, logger); - } - - var oldClose = server.close; - - server.close = function(callback) { - var args = Array.prototype.slice.call(arguments); - oldClose.apply(server, args); - - server.provider.close(function(err) { - if (err) return callback(err); - Object.keys(connections).forEach(key => { - try { - connections[key].destroy(); - } catch (error) {} - }) - }); - }; - - return server; - } -}; - -const defaultOptions = { - logger: { - log: function() {} - }, - ws: true -} - -var _applyDefaultOptions = function(options) { - return _.merge({}, defaultOptions, options) -} diff --git a/lib/statemanager.js b/lib/statemanager.js deleted file mode 100644 index e6525788be..0000000000 --- a/lib/statemanager.js +++ /dev/null @@ -1,886 +0,0 @@ -var Account = require('ethereumjs-account'); -var Block = require('ethereumjs-block'); -var VM = require('ethereumjs-vm'); -var RuntimeError = require('./utils/runtimeerror'); -var Trie = require('merkle-patricia-tree'); -var FakeTransaction = require('ethereumjs-tx/fake.js'); -var utils = require('ethereumjs-util'); -var seedrandom = require('seedrandom'); -var bip39 = require('bip39'); -var wallet = require('ethereumjs-wallet'); -var hdkey = require('ethereumjs-wallet/hdkey'); -var async = require("async"); -var BlockchainDouble = require("./blockchain_double.js"); -var ForkedBlockchain = require("./utils/forkedblockchain.js"); -var Web3 = require('web3'); -var util = require("util"); -var sigUtil = require('eth-sig-util') -var _ = require("lodash"); - -var to = require('./utils/to'); -var random = require('./utils/random'); -var txhelper = require('./utils/txhelper'); -var TXRejectedError = require('./utils/txrejectederror'); - -StateManager = function(options, provider) { - var self = this; - - this.options = options = this._applyDefaultOptions(options || {}) - - if (options.fork) { - this.blockchain = new ForkedBlockchain(options); - } else { - this.blockchain = new BlockchainDouble(options); - } - - this.vm = this.blockchain.vm; - this.stateTrie = this.blockchain.stateTrie; - - this.accounts = {}; - this.secure = !!options.secure; - this.account_passwords = {} - this.personal_accounts = {} - this.total_accounts = options.total_accounts; - this.coinbase = null; - - this.latest_filter_id = 1; - - // This queue manages actions that shouldn't be run in parallel. - // The action_processing flag ensures new actions are queued instead of - // run immediately. - this.action_queue = []; - this.action_processing == false; - - this.snapshots = []; - this.logger = options.logger; - this.net_version = options.network_id; - this.mnemonic = options.mnemonic; - this.wallet = hdkey.fromMasterSeed(bip39.mnemonicToSeed(this.mnemonic)); - this.wallet_hdpath = options.hdPath; - - this.gasPriceVal = to.rpcQuantityHexString(options.gasPrice); - - this.is_mining = true; - this.blockTime = options.blockTime; - this.is_mining_on_interval = !!options.blockTime; - this.mining_interval_timeout = null; - - this._provider = provider; -} - -const defaultOptions = { - total_accounts: 10, - gasPrice: '0x77359400', //2 gwei - default_balance_ether: 100, - unlocked_accounts: [], - hdPath: "m/44'/60'/0'/0/" -} - -StateManager.prototype._applyDefaultOptions = function(options) { - // do this so that we can use the same seed on our next run and get the same - // results without explicitly setting a seed up front - if (!options.seed) { - options.seed = random.randomAlphaNumericString(10, seedrandom()) - } - - // generate a randomized default mnemonic - if (!options.mnemonic) { - let randomBytes = random.randomBytes(16, seedrandom(options.seed)) - options.mnemonic = bip39.entropyToMnemonic(randomBytes.toString("hex")) - } - - if (!options.fork && !options.network_id) { - options.network_id = (new Date()).getTime(); - } - - // We want this function to mutate the options object so that we can report - // our settings back to our consumer application (e.g., ganache) - return _.merge(options, defaultOptions, Object.assign({}, options)); -} - -StateManager.prototype.initialize = function(callback) { - var self = this; - - var accounts = []; - - let defaultBalanceWei = to.hex(Web3.utils.toWei(self.options.default_balance_ether.toString(), 'ether')); - - if (self.options.accounts) { - accounts = self.options.accounts.map(self.createAccount.bind(self)); - } else { - if (!self.total_accounts) { - return callback(new Error('Cannot initialize chain: either options.accounts or options.total_accounts must be specified')) - } - - for (var i = 0; i < self.total_accounts; i++) { - accounts.push(self.createAccount({ - index: i, - balance: defaultBalanceWei - })); - } - } - - self.coinbase = to.hex(accounts[0].address); - self.accounts = {}; - - accounts.forEach(function(data) { - self.accounts[data.address] = data; - self.personal_accounts[data.address.toLowerCase()] = true; - }); - - // Turn array into object, mostly for speed purposes. - // No need for caller to specify private keys. - self.unlocked_accounts = self.options.unlocked_accounts.reduce(function(obj, address) { - // If it doesn't have a hex prefix, must be a number (either a string or number type). - if ((address + "").indexOf("0x") != 0) { - let idx = parseInt(address) - let account = accounts[idx] - if (!account) { - throw new Error(`Account at index ${idx} not found. Max index available is ${accounts.length - 1}.`) - } - address = account.address.toLowerCase(); - } - - obj[address.toLowerCase()] = true; // can be any value - return obj; - }, {}); - - if (!self.secure) { - accounts.forEach(function(data) { - self.unlocked_accounts[data.address.toLowerCase()] = data; - }); - } - - self.blockchain.initialize(accounts, function(err) { - if (err) return callback(err); - - // If the user didn't pass a specific version id in, then use the - // forked blockchain's version (if it exists) or create our own. - if (!self.net_version) { - self.net_version = self.blockchain.fork_version - } - - if (self.is_mining_on_interval) { - self.mineOnInterval(); - } - - callback(); - }); -}; - -StateManager.prototype.mineOnInterval = function() { - var self = this; - - // For good measure. - clearTimeout(self.mining_interval_timeout); - self.mining_interval_timeout = null; - - self.mining_interval_timeout = setTimeout(function() { - self._provider.send({ - method: 'evm_mine' - }, - self.mineOnInterval.bind(self) - ); - - }, this.blockTime * 1000); - - // Ensure this won't keep a node process open. - if (this.mining_interval_timeout && this.mining_interval_timeout.unref) { - this.mining_interval_timeout.unref(); - } -}; - -StateManager.prototype.createAccount = function(opts, i) { - var secretKey; - var balance; - - if (opts.generate) { - secretKey = wallet.generate().getPrivateKey(); - } else if (opts.secretKey) { - secretKey = utils.toBuffer(to.hex(opts.secretKey)); - } else { - var index = (typeof(opts.index) === 'undefined') ? i : opts.index; - var acct = this.wallet.derivePath(this.wallet_hdpath + index) // index is a number - secretKey = acct.getWallet().getPrivateKey() // Buffer - } - - var publicKey = utils.privateToPublic(secretKey); - var address = utils.publicToAddress(publicKey); - - var account = new Account(); - - account.balance = to.hex(opts.balance) - - var data = { - secretKey: secretKey, - publicKey: publicKey, - address: to.hex(address).toLowerCase(), - account: account - }; - - return data; -}; - -StateManager.prototype.blockNumber = function(callback) { - return this.blockchain.getHeight(callback); -}; - -StateManager.prototype.gasPrice = function() { - return this.gasPriceVal; -} - -StateManager.prototype.getBalance = function(address, number, callback) { - this.blockchain.getBalance(address, number, function(err, balance) { - if (balance) { - balance = to.rpcQuantityHexString(balance); - } - callback(err, balance); - }); -} - -StateManager.prototype.getTransactionCount = function(address, number, callback) { - this.blockchain.getNonce(address, number, function(err, nonce) { - if (nonce) { - nonce = to.rpcQuantityHexString(nonce); - } - callback(err, nonce); - }); -} - -StateManager.prototype.getCode = function(address, number, callback) { - this.blockchain.getCode(address, number, function(err, code) { - if (code) { - code = to.hex(code); - } - callback(err, code); - }); -} - -StateManager.prototype.queueRawTransaction = function(rawTx, callback) { - var data = Buffer.from(utils.stripHexPrefix(rawTx), 'hex'); - - var tx = new FakeTransaction(data); - var txParams = { - from: tx.from.toString('hex'), - to: tx.to.toString('hex'), - gas: tx.gasLimit.toString('hex'), - gasPrice: tx.gasPrice.toString('hex'), - value: tx.value.toString('hex'), - data: tx.data.toString('hex'), - nonce: tx.nonce.toString('hex'), - } - - if (tx.v && tx.v.length > 0 && - tx.r && tx.r.length > 0 && - tx.s && tx.s.length > 0) { - txParams.v = tx.v.toString('hex'); - txParams.r = tx.r.toString('hex'); - txParams.s = tx.s.toString('hex'); - } - - this.queueTransaction("eth_sendRawTransaction", txParams, null, callback); -}; - -StateManager.prototype.queueStorage = function(address, position, block, callback) { - this.action_queue.push({ - method: "eth_getStorageAt", - address: utils.addHexPrefix(address), - position: utils.addHexPrefix(position), - block: block, - callback: callback - }); - - // We know there's work, so get started. - this.processNextAction(); -} - -StateManager.prototype.queueTransaction = function(method, tx_params, block_number, callback) { - if (tx_params.from == null) { - callback(new TXRejectedError("from not found; is required")); - return; - } - - // use toLowerCase() to properly handle from addresses meant to be validated. - tx_params.from = utils.addHexPrefix(tx_params.from).toLowerCase(); - - if (method == "eth_sendTransaction" && - this.accounts[tx_params.from] == null && - this.unlocked_accounts[tx_params.from] == null) { - - return callback(new TXRejectedError("sender account not recognized")); - } - - if (method == "eth_sendTransaction" && this.unlocked_accounts[tx_params.from] == null) { - return callback(new TXRejectedError("signer account is locked")); - } - - var rawTx = { - gasPrice: "0x1", - gasLimit: to.hex(this.blockchain.defaultTransactionGasLimit), - value: '0x0', - }; - - if (tx_params.gas != null) { - rawTx.gasLimit = utils.addHexPrefix(tx_params.gas); - } - - if (tx_params.gasPrice != null) { - rawTx.gasPrice = utils.addHexPrefix(tx_params.gasPrice); - } else { - rawTx.gasPrice = this.gasPriceVal; - } - - if (tx_params.to != null) { - rawTx.to = utils.addHexPrefix(tx_params.to); - } - - if (tx_params.value != null) { - rawTx.value = utils.addHexPrefix(tx_params.value); - } - - if (tx_params.data != null) { - rawTx.data = utils.addHexPrefix(tx_params.data); - } - - if (tx_params.nonce != null) { - rawTx.nonce = utils.addHexPrefix(tx_params.nonce); - } - - if (tx_params.v != null && tx_params.s != null && tx_params.v != null) { - rawTx.v = utils.addHexPrefix(tx_params.v); - rawTx.r = utils.addHexPrefix(tx_params.r); - rawTx.s = utils.addHexPrefix(tx_params.s); - } - - // some tools use a null or empty `to` field when doing contract deployments - if (rawTx.to == '0x0' || rawTx.to == '') { - delete rawTx.to - } - - // Error checks - if (rawTx.to && typeof rawTx.to != "string") { - return callback(new TXRejectedError("Invalid to address")); - } - - // If the transaction has a higher gas limit than the block gas limit, error. - if (to.number(rawTx.gasLimit) > to.number(this.blockchain.blockGasLimit)) { - return callback(new TXRejectedError("Exceeds block gas limit")); - } - - // Get the nonce for this address, taking account any transactions already queued. - var self = this; - var address = utils.toBuffer(tx_params.from); - - // we don't call createFakeTransactionWithCorrectNonce here because then we'd need to worry - // about nonce calculation for the items pending in the action_queue. - // Instead, we simply create a `FakeTransaction` and bail on validation - // errors so that we fail fast when we have bad tx input - - try { - let tx = new FakeTransaction(rawTx); - tx.from = address; - } catch (err) { - return callback(err); - } - - self.action_queue.push({ - method: method, - from: tx_params.from, - tx: rawTx, - callback: callback, - blockNumber: block_number, - }); - - // We know there's work, so get started. - self.processNextAction(); -}; - -StateManager.prototype.queueTransactionTrace = function(tx_hash, params, callback) { - this.action_queue.push({ - method: "debug_traceTransaction", - hash: to.hex(tx_hash), - params: params, - callback: callback - }); - - // We know there's work, so get started. - this.processNextAction(); -}; - -StateManager.prototype.processNextAction = function(override) { - var self = this; - - if (override != true) { - if (this.action_processing == true || this.action_queue.length == 0) { - return; - } - } - - var queued = this.action_queue.shift(); - - // Set the flag that we're currently processing something. - this.action_processing = true; - - var intermediary = function(err, result) { - queued.callback(err, result); - - if (self.action_queue.length > 0) { - self.processNextAction(true); - } else { - self.action_processing = false; - } - }; - - if (typeof queued.method == "function") { - var result = queued.method(); - return intermediary(null, result); - } else if (queued.method == "eth_getStorageAt") { - this.blockchain.getStorage(queued.address, queued.position, queued.block, function(err, result) { - if (err) return intermediary(err); - - if (result) { - result = utils.rlp.decode(result); - } - - result = to.hex(result || 0); - intermediary(null, result); - }); - } else if (queued.method == "debug_traceTransaction") { - this.blockchain.processTransactionTrace(queued.hash, queued.params, intermediary); - } else if (queued.method == "eth_sendTransaction" || queued.method == "eth_sendRawTransaction") { - this.processTransaction(queued.from, queued.tx, intermediary); - } else if (queued.method == "eth_call") { - this.processCall(queued.from, queued.tx, queued.blockNumber, intermediary); - } else if (queued.method == "eth_estimateGas") { - this.processGasEstimate(queued.from, queued.tx, queued.blockNumber, intermediary); - } -}; - -StateManager.prototype.sign = function(address, dataToSign) { - var account = this.accounts[to.hex(address).toLowerCase()]; - - if (!account) { - throw new Error("cannot sign data; no private key"); - } - - var secretKey = account.secretKey; - var msg = Buffer.from(dataToSign.replace('0x',''), 'hex'); - var msgHash = utils.hashPersonalMessage(msg); - var sgn = utils.ecsign(msgHash, Buffer.from(secretKey)); - return utils.toRpcSig(sgn.v, sgn.r, sgn.s); -}; - -StateManager.prototype.signTypedData = function(address, typedDataToSign) { - var account = this.accounts[to.hex(address).toLowerCase()]; - if (!account) { - throw new Error("cannot sign data; no private key"); - } - - if(!typedDataToSign.types) { - throw new Error("cannot sign data; types missing"); - } - - if(!typedDataToSign.types.EIP712Domain) { - throw new Error("cannot sign data; EIP712Domain definition missing"); - } - - if(!typedDataToSign.domain) { - throw new Error("cannot sign data; domain missing"); - } - - if(!typedDataToSign.primaryType) { - throw new Error("cannot sign data; primaryType missing"); - } - - if(!typedDataToSign.message) { - throw new Error("cannot sign data; message missing"); - } - - return sigUtil.signTypedData(account.secretKey, { data: typedDataToSign }); -}; - -StateManager.prototype.printTransactionReceipt = function(tx_hash, error, callback){ - var self = this; - - self.blockchain.getTransactionReceipt(tx_hash, function(err, receipt) { - if (err) return callback(err); - - self.blockchain.latestBlock(function(err, block) { - if (err) return callback(err); - - receipt = receipt.toJSON(); - - self.logger.log(""); - self.logger.log(" Transaction: " + tx_hash); - - if (receipt.contractAddress != null) { - self.logger.log(" Contract created: " + receipt.contractAddress); - } - - self.logger.log(" Gas usage: " + parseInt(receipt.gasUsed, 16)); - self.logger.log(" Block Number: " + parseInt(receipt.blockNumber, 16)); - self.logger.log(" Block Time: " + new Date(to.number(block.header.timestamp) * 1000).toString()); - - if (error) { - self.logger.log(" Runtime Error: " + error.error); - if (error.reason) { - self.logger.log(" Revert reason: " + error.reason); - } - } - - self.logger.log(""); - - callback(null, tx_hash); - }); - }); -} - -StateManager.prototype.processBlock = function(timestamp, callback) { - var self = this; - - if (typeof timestamp == "function") { - callback = timestamp; - timestamp = null; - } - - self.blockchain.processNextBlock(timestamp, function(runtime_error, transactions, vm_output) { - if (runtime_error && runtime_error instanceof RuntimeError == false) { - // This is bad. Get out. - return callback(runtime_error, transactions, vm_output); - } - - // TODO: Can we refactor printTransactionReceipt so it's synchronous? - // We technically have the raw vm receipts (though they're not full receipts here...). - async.eachSeries(transactions, function(tx, finished_printing) { - var hash = to.hex(tx.hash()); - var error = runtime_error == null ? {results: {}} : runtime_error; - self.printTransactionReceipt(hash, error.results[hash], finished_printing); - }, callback(runtime_error, transactions, vm_output)); - }); -} - -StateManager.prototype.processBlocks = function(total_blocks, callback) { - var self = this; - - if (typeof total_blocks == "function") { - callback = total_blocks; - total_blocks = null; - } - - // Note: VM errors (errors that the VM directly returns) trump all runtime errors. - var runtime_error = null; - var amount_processed = 0; - - async.whilst(function() { - var shouldContinue; - - if (total_blocks == null) { - shouldContinue = self.blockchain.pending_transactions.length > 0; - } else { - shouldContinue = amount_processed < total_blocks; - } - - return shouldContinue; - }, function(done) { - self.processBlock(function(err, transactions, vm_output) { - amount_processed += 1; - - if (err) { - if (err instanceof RuntimeError == false) { - // This is bad. Get out. - return done(err); - } - - // We must have a RuntimeError. Merge results if we've found - // other runtime errors during this execution. - if (runtime_error == null) { - runtime_error = err; - } else { - runtime_error.combine(err); - } - } - - // Note we don't quit on runtime errors. We keep processing transactions. - done(); - }); - }, function(err) { - // Remember: vm errors trump runtime errors - callback(err || runtime_error); - }); -}; - -StateManager.prototype.processCall = function (from, rawTx, blockNumber, callback) { - var self = this; - - self.createFakeTransactionWithCorrectNonce(rawTx, from, function(err, tx) { - if (err) return callback(err); - - self.blockchain.processCall(tx, blockNumber, function (err, results) { - if (err) { - return callback(err); - } - - var result = '0x0' - if (!results.error && results.vm.return) { - result = to.hex(results.vm.return); - } else if (results.error) { - self.logger.log(`Error processing call: ${results.error}`) - } - - return callback(null, result); - }); - }); -}; - -StateManager.prototype.processGasEstimate = function (from, rawTx, blockNumber, callback) { - var self = this; - - self.createFakeTransactionWithCorrectNonce(rawTx, from, function(err, tx) { - if (err) return callback(err); - - self.blockchain.processCall(tx, blockNumber, function (err, results) { - if (err) { - return callback(err); - } - var result = '0x0' - if (!results.error) { - result = results.gasRefund ? to.hex(results.gasUsed.add(results.gasRefund)) : to.hex(results.gasUsed); - } else { - self.logger.log(`Error calculating gas estimate: ${results.error}`) - } - return callback(null, result); - }); - }); -} - -StateManager.prototype.processTransaction = function(from, rawTx, callback) { - var self = this; - - self.createFakeTransactionWithCorrectNonce(rawTx, from, function(err, tx) { - if (err) return callback(err); - - self.blockchain.queueTransaction(tx); - - var tx_hash = to.hex(tx.hash()); - - // If we're not currently mining or we're mining on an interval, - // only queue the transaction, don't process it. - if (self.is_mining == false || self.is_mining_on_interval) { - return callback(null, tx_hash); - } - - self.processBlocks(function (err) { - if (err) return callback(err); - callback(null, tx_hash); - }); - }); -}; - -StateManager.prototype.getTransactionReceipt = function(hash, callback) { - this.blockchain.getTransactionReceipt(hash, function(err, receipt) { - if (err && err.notFound) { - // Return null if the receipt's not found. - return callback(null, null); - } - callback(err, receipt); - }); -}; - -StateManager.prototype.getBlock = function(hash_or_number, callback) { - this.blockchain.getBlock(hash_or_number, callback); -}; - -StateManager.prototype.getLogs = function(filter, callback) { - var self = this; - - // filter.address may be a single address or an array - // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs - var expectedAddress = filter.address && (Array.isArray(filter.address) ? filter.address : [filter.address]); - expectedAddress = expectedAddress && expectedAddress.map(function(a) { return a.toLowerCase() }); - var expectedTopics = filter.topics || []; - - async.parallel({ - fromBlock: this.blockchain.getEffectiveBlockNumber.bind(this.blockchain, filter.fromBlock || "latest"), - toBlock: this.blockchain.getEffectiveBlockNumber.bind(this.blockchain, filter.toBlock || "latest"), - latestBlock: this.blockchain.getEffectiveBlockNumber.bind(this.blockchain, "latest") - }, function(err, results) { - var fromBlock = results.fromBlock; - var toBlock = results.toBlock; - var latestBlock = results.latestBlock; - - if (toBlock > latestBlock) { - toBlock = latestBlock; - } - - var logs = []; - var current = fromBlock; - - async.whilst(function() { - return current <= toBlock; - }, function(finished) { - self.blockchain.getBlockLogs(current, function(err, blockLogs) { - if (err) return finished(err); - - // Filter logs that match the address - var filtered = !expectedAddress ? blockLogs : blockLogs.filter(function(log) { - return expectedAddress.indexOf(log.address.toLowerCase()) > -1; - }); - - // Now filter based on topics. - filtered = filtered.filter(function(log) { - var keep = true; - for (var i = 0; i < expectedTopics.length; i++) { - var expectedTopic = expectedTopics[i]; - var logTopic = log.topics[i]; - if (expectedTopic == null) continue; - var isMatch = Array.isArray(expectedTopic) - ? expectedTopic.includes(logTopic) - : expectedTopic === logTopic; - if (i >= log.topics.length || !isMatch) { - keep = false; - break; - } - } - return keep; - }); - - logs.push.apply(logs, filtered); - - current += 1; - finished(); - }); - }, function(err) { - if (err) return callback(err); - - logs = logs.map(function(log) { - return log.toJSON(); - }); - - callback(err, logs); - }); - - }); -}; - -// Note: Snapshots have 1-based ids. -StateManager.prototype.snapshot = function(callback) { - var self = this; - - this.blockchain.getHeight(function(err, blockNumber) { - if (err) return callback(err); - - self.snapshots.push({ - blockNumber: blockNumber, - timeAdjustment: self.blockchain.timeAdjustment - }); - - self.logger.log("Saved snapshot #" + self.snapshots.length); - - callback(null, to.hex(self.snapshots.length)); - }); -}; - -StateManager.prototype.revert = function(snapshot_id, callback) { - var self = this; - - // Convert from hex. - snapshot_id = utils.bufferToInt(snapshot_id); - - this.logger.log("Reverting to snapshot #" + snapshot_id); - - if (snapshot_id > this.snapshots.length) { - return false; - } - - // Convert to zero based. - snapshot_id = snapshot_id - 1; - var timeAdjustment = this.snapshots[snapshot_id].timeAdjustment; - - // Loop through each snapshot with a higher id than the current one. - async.whilst(function() { - return self.snapshots.length > snapshot_id - }, function(nextSnapshot) { - var snapshot = self.snapshots.pop(); - - // For each snapshot, asynchronously pop off the blocks it represents. - async.during(function(doneWithTest) { - self.blockchain.getHeight(function(err, blockNumber) { - if (err) return doneWithTest(err); - - doneWithTest(null, blockNumber > snapshot.blockNumber) - }); - }, function(nextBlock) { - self.blockchain.popBlock(function(err) { - if (err) return nextBlock(err); - nextBlock(); - }); - }, nextSnapshot); - - - }, function(err) { - if (err) return callback(err); - - // Pending transactions are removed when you revert. - self.blockchain.clearPendingTransactions(); - // The time adjustment is restored to its prior state - self.blockchain.timeAdjustment = timeAdjustment; - - callback(null, true); - }); -}; - -StateManager.prototype.hasContractCode = function(address, callback) { - this.vm.stateManager.getContractCode( address, function( err, result ) { - if( err != null ) { - callback( err, false ); - } else { - callback( null, true ); - } - }); -} - -StateManager.prototype.startMining = function(callback) { - this.is_mining = true; - - if (this.is_mining_on_interval) { - this.mineOnInterval(); - callback(); - } else { - this.processBlocks(callback); - } -}; - -StateManager.prototype.stopMining = function(callback) { - this.is_mining = false; - clearTimeout(this.mining_interval_timeout); - this.mining_interval_timeout = null; - callback(); -}; - -StateManager.prototype.isUnlocked = function(address) { - return this.unlocked_accounts[address.toLowerCase()] != null; -}; - -StateManager.prototype.createFakeTransactionWithCorrectNonce = function(rawTx, from, callback) { - const self = this; - self.blockchain.getQueuedNonce(from, (err, expectedNonce) => { - if (err) return callback(err); - - var tx = new FakeTransaction(rawTx); - tx.from = from; - - // If the user specified a nonce, use that instead. - if (rawTx.nonce == null) { - // account for transactions waiting in the tx queue - tx.nonce = to.hex(expectedNonce); - } else { - if (to.number(rawTx.nonce) !== to.number(expectedNonce)) { - return callback(new TXRejectedError(`the tx doesn't have the correct nonce. ` + - `account has nonce of: ${to.number(expectedNonce)} ` + - `tx has nonce of: ${to.number(tx.nonce)}`)) - } - } - callback(null, tx) - }); -} -module.exports = StateManager; diff --git a/lib/subproviders/delayedblockfilter.js b/lib/subproviders/delayedblockfilter.js deleted file mode 100644 index a95d2366f1..0000000000 --- a/lib/subproviders/delayedblockfilter.js +++ /dev/null @@ -1,123 +0,0 @@ -// It's unforutnate we have to have this subprovider, but it's because -// we instamine, and web3 isn't written in a way that supports instamining -// (i.e., it sets up the filter after the transaction has been processed). -// This block filter will ensure that each block filter will always see -// the change from the last block to the current block. -// -// Note: An added benefit of this is that it shaves off a signifcant -// amount of time from tests that use web3 and block filters. - -var Subprovider = require('web3-provider-engine/subproviders/subprovider.js'); -var inherits = require("util").inherits; -var async = require("async"); -var to = require("../utils/to"); - -inherits(DelayedBlockFilter, Subprovider); - -module.exports = DelayedBlockFilter; - -function DelayedBlockFilter() { - this.watching = {}; -}; - -DelayedBlockFilter.prototype.handleRequest = function(payload, next, end) { - if (payload.method == "eth_newBlockFilter") return this.handleNewBlockFilter(payload, next, end); - if (payload.method == "eth_getFilterChanges") return this.handleGetFilterChanges(payload, next, end); - - next(); -}; - -DelayedBlockFilter.prototype.handleNewBlockFilter = function(payload, next, end) { - var self = this; - - // Let this filter process and add it to our watch list. - next(function(err, result, cb) { - if (err) return cb(); - self.watching[result] = true; - cb(); - }); -} - -DelayedBlockFilter.prototype.handleGetFilterChanges = function(payload, next, end) { - var self = this; - var filter_id = payload.params[0]; - - if (!this.watching[filter_id]) return next(); - - // Get the changes, and then alter the result. - next(function(err, result, cb) { - if (err) return cb(); - - var currentBlockHash; - var previousBlockHash; - var blockNumber; - - async.series([ - function(c) { - // If we have a result, use it. - if (result.length != 0) { - currentBlockHash = result[0]; - c(); - } else { - // Otherwise, get the current block number. - self.emitPayload({ - method: "eth_blockNumber" - }, function(err, res) { - if (err) return c(err); - blockNumber = to.number(res.result); - c(); - }); - } - }, - function(c) { - // If we got a block number above, meaning, we didn't get a block hash, - // skip this step. - if (blockNumber) return c(); - - // If not skipped, then we got a block hash, and we need to get a block number from it. - self.emitPayload({ - method: "eth_getBlockByHash", - params: [currentBlockHash, false] - }, function(err, res) { - if (err) return c(err); - blockNumber = to.number(res.result.number); - c(); - }) - }, - function(c) { - // If we're at block 0, return no changes. See final function below. - if (blockNumber == 0) { - previousBlockHash = undefined; - return c(); - } - - // If at this point, we do have a block number, so let's subtract one - // from it and get the block hash of the block before it. - blockNumber = blockNumber - 1; - self.emitPayload({ - method: "eth_getBlockByNumber", - params: [blockNumber, false] - }, function(err, res) { - if (err) return c(err); - previousBlockHash = res.result.hash; - c(); - }); - } - ], function(err) { - if (err) { - // Unfortunately the subprovider code doesn't let us return an error - // through the callback cb(). So we'll just ignore it.... (famous last words). - } - - // If we got the previous block, use it. Otherwise do nothing. - // Then stop watching because we only want on getFilterChanges to react this way. - if (previousBlockHash) { - result[0] = previousBlockHash; - } - - delete self.watching[filter_id]; - cb(); - }) - }); - -}; diff --git a/lib/subproviders/geth_api_double.js b/lib/subproviders/geth_api_double.js deleted file mode 100644 index 8241ee8468..0000000000 --- a/lib/subproviders/geth_api_double.js +++ /dev/null @@ -1,820 +0,0 @@ -var utils = require('ethereumjs-util'); -var inherits = require('util').inherits; -var StateManager = require('../statemanager.js'); -var to = require('../utils/to'); -var txhelper = require('../utils/txhelper'); -var blockHelper = require('../utils/block_helper'); -var pkg = require('../../package.json'); -var _ = require('lodash'); - -var Subprovider = require('web3-provider-engine/subproviders/subprovider.js'); - -inherits(GethApiDouble, Subprovider) - -function GethApiDouble(options, provider) { - var self = this; - - this.state = options.state || new StateManager(options, provider); - this.options = options; - this.initialized = false; - - this.initialization_error = null; - this.post_initialization_callbacks = []; - - this.state.initialize(function(err) { - if (err) { - self.initialization_error = err; - } - self.initialized = true; - - var callbacks = self.post_initialization_callbacks; - self.post_initialization_callbacks = []; - - callbacks.forEach(function(callback) { - setImmediate(function() { - callback(self.initialization_error, self.state); - }); - }); - }); -} - -GethApiDouble.prototype.waitForInitialization = function(callback) { - var self = this; - if (self.initialized == false) { - self.post_initialization_callbacks.push(callback); - } else { - callback(self.initialization_error, self.state); - } -} - -// Function to not pass methods through until initialization is finished -GethApiDouble.prototype.handleRequest = function(payload, next, end) { - var self = this; - - if (self.initialization_error != null) { - return end(self.initialization_error); - } - - if (self.initialized == false) { - self.waitForInitialization(self.getDelayedHandler(payload, next, end)); - return; - } - - var method = self[payload.method]; - - if (method == null) { - return end(new Error("Method " + payload.method + " not supported.")); - } - - var params = payload.params || []; - var args = [].concat(params); - - var addedBlockParam = false; - - if (self.requiresDefaultBlockParameter(payload.method) && args.length < method.length - 1) { - args.push("latest"); - addedBlockParam = true; - } - - args.push(end); - - // avoid crash by checking to make sure that we haven't specified too many arguments - if ( - args.length > method.length - || (method.minLength !== undefined && args.length < method.minLength) - || (method.minLength === undefined && args.length < method.length) - ){ - - var errorMessage = `Incorrect number of arguments. Method '${payload.method}' requires `; - if (method.minLength) { - errorMessage += `between ${method.minLength - 1} and ${method.length - 1} arguments. `; - } else { - errorMessage += `exactly ${method.length - 1} arguments. `; - } - - if (addedBlockParam) { - errorMessage += 'Including the implicit block argument, r'; - } else { - // new sentence, capitalize it. - errorMessage += 'R'; - } - errorMessage += `equest specified ${args.length - 1} arguments: ${JSON.stringify(args)}.` - - return end(new Error(errorMessage)); - } - - method.apply(self, args); -}; - -GethApiDouble.prototype.getDelayedHandler = function(payload, next, end) { - var self = this; - return function(err, state) { - if (err) { - end(err); - } - self.handleRequest(payload, next, end); - } -} - -GethApiDouble.prototype.requiresDefaultBlockParameter = function(method) { - // object for O(1) lookup. - var methods = { - "eth_getBalance": true, - "eth_getCode": true, - "eth_getTransactionCount": true, - "eth_getStorageAt": true, - "eth_call": true, - "eth_estimateGas": true - }; - - return methods[method] === true; -}; - -// Handle individual requests. - -GethApiDouble.prototype.eth_accounts = function(callback) { - callback(null, Object.keys(this.state.accounts)); -}; - -GethApiDouble.prototype.eth_blockNumber = function(callback) { - this.state.blockNumber(function(err, result) { - if (err) return callback(err); - callback(null, to.hex(result)); - }); -}; - -GethApiDouble.prototype.eth_coinbase = function(callback) { - callback(null, this.state.coinbase); -}; - -GethApiDouble.prototype.eth_mining = function(callback) { - callback(null, this.state.is_mining); -}; - -GethApiDouble.prototype.eth_hashrate = function(callback) { - callback(null, '0x0'); -}; - -GethApiDouble.prototype.eth_gasPrice = function(callback) { - callback(null, utils.addHexPrefix(this.state.gasPrice())); -}; - -GethApiDouble.prototype.eth_getBalance = function(address, block_number, callback) { - this.state.getBalance(address, block_number, callback); -}; - -GethApiDouble.prototype.eth_getCode = function(address, block_number, callback) { - this.state.getCode(address, block_number, callback); -}; - -GethApiDouble.prototype.eth_getBlockByNumber = function(block_number, include_full_transactions, callback) { - this.state.blockchain.getBlock(block_number, function(err, block) { - if (err) { - if (err.message && err.message.indexOf("index out of range") >= 0) { - return callback(null, null); - } else { - return callback(err); - } - } - - callback(null, blockHelper.toJSON(block, include_full_transactions)); - }); -}; - -GethApiDouble.prototype.eth_getBlockByHash = function(tx_hash, include_full_transactions, callback) { - this.eth_getBlockByNumber.apply(this, arguments); -}; - -GethApiDouble.prototype.eth_getBlockTransactionCountByNumber = function(block_number, callback) { - this.state.blockchain.getBlock(block_number, function(err, block) { - if (err) { - if (err.message.indexOf("index out of range")) { - // block doesn't exist - return callback(null, 0); - } else { - return callback(err); - } - } - callback(null, block.transactions.length); - }); -} - -GethApiDouble.prototype.eth_getBlockTransactionCountByHash = function(block_hash, callback) { - this.eth_getBlockTransactionCountByNumber.apply(this, arguments); -} - -GethApiDouble.prototype.eth_getTransactionReceipt = function(hash, callback) { - this.state.getTransactionReceipt(hash, function(err, receipt) { - if (err) return callback(err); - - var result = null; - - if (receipt){ - result = receipt.toJSON(); - } - callback(null, result); - }); -}; - -GethApiDouble.prototype.eth_getTransactionByHash = function(hash, callback) { - this.state.getTransactionReceipt(hash, function(err, receipt) { - if (err) return callback(err); - - var result = null; - - if (receipt) { - result = txhelper.toJSON(receipt.tx, receipt.block) - } - - callback(null, result); - }); -} - -GethApiDouble.prototype.eth_getTransactionByBlockHashAndIndex = function(hash_or_number, index, callback) { - var self = this; - - index = to.number(index); - - this.state.getBlock(hash_or_number, function(err, block) { - if (err) { - // block doesn't exist by that hash - if (err.notFound) { - return callback(null, null); - } else { - return callback(err); - } - } - - if (index >= block.transactions.length) { - return callback(new Error("Transaction at index " + to.hex(index) + " does not exist in block.")); - } - - var tx = block.transactions[index]; - var result = txhelper.toJSON(tx, block); - - callback(null, result); - }); -}; - -GethApiDouble.prototype.eth_getTransactionByBlockNumberAndIndex = function(hash_or_number, index, callback) { - this.eth_getTransactionByBlockHashAndIndex(hash_or_number, index, callback); -}; - -GethApiDouble.prototype.eth_getTransactionCount = function(address, block_number, callback) { - this.state.getTransactionCount(address, block_number, (err, count) => { - if (err && err.message && err.message.indexOf("index out of range") >= 0) { - err = new Error("Unknown block number") - } - return callback(err, count); - }); -} - -GethApiDouble.prototype.eth_sign = function(address, dataToSign, callback) { - var result; - var error; - - try { - result = this.state.sign(address, dataToSign); - } catch (e) { - error = e; - } - - callback(error, result); -}; - -GethApiDouble.prototype.eth_signTypedData = function(address, typedDataToSign, callback) { - var result; - var error; - - try { - result = this.state.signTypedData(address, typedDataToSign); - } catch (e) { - error = e; - } - - callback(error, result); -}; - -GethApiDouble.prototype.eth_sendTransaction = function(tx_data, callback) { - this.state.queueTransaction("eth_sendTransaction", tx_data, null, callback); -}; - -GethApiDouble.prototype.eth_sendRawTransaction = function(rawTx, callback) { - this.state.queueRawTransaction(rawTx, callback); -}; - -GethApiDouble.prototype.eth_call = function(tx_data, block_number, callback) { - if (!tx_data.gas) { - tx_data.gas = this.state.blockchain.blockGasLimit; - } - - this.state.queueTransaction("eth_call", tx_data, block_number, callback); // :( -}; - -GethApiDouble.prototype.eth_estimateGas = function(tx_data, block_number, callback) { - if (!tx_data.gas) { - tx_data.gas = this.state.blockchain.blockGasLimit; - } - this.state.queueTransaction("eth_estimateGas", tx_data, block_number, callback); -}; - -GethApiDouble.prototype.eth_getStorageAt = function(address, position, block_number, callback) { - this.state.queueStorage(address, position, block_number, callback); -}; - -GethApiDouble.prototype.eth_newBlockFilter = function(callback) { - var filter_id = utils.addHexPrefix(utils.intToHex(this.state.latest_filter_id)); - this.state.latest_filter_id += 1; - callback(null, filter_id); -}; - -GethApiDouble.prototype.eth_getFilterChanges = function(filter_id, callback) { - var blockHash = this.state.latestBlock().hash().toString("hex"); - // Mine a block after each request to getFilterChanges so block filters work. - this.state.mine(); - callback(null, [blockHash]); -}; - -GethApiDouble.prototype.eth_getLogs = function(filter, callback) { - this.state.getLogs(filter, callback); -}; - -GethApiDouble.prototype.eth_uninstallFilter = function(filter_id, callback) { - callback(null, true); -}; - -GethApiDouble.prototype.eth_protocolVersion = function(callback) { - callback(null, "63"); -}; - -GethApiDouble.prototype.bzz_hive = function(callback) { - callback(null, []); -}; - -GethApiDouble.prototype.bzz_info = function(callback) { - callback(null, []); -}; - -GethApiDouble.prototype.shh_version = function(callback) { - callback(null, "2"); -}; - -GethApiDouble.prototype.eth_getCompilers = function(callback) { - callback(null, []); -} - -GethApiDouble.prototype.eth_syncing = function(callback) { - callback(null, false); -}; - -GethApiDouble.prototype.net_listening = function(callback) { - callback(null, true); -}; - -GethApiDouble.prototype.net_peerCount = function(callback) { - callback(null, 0); -}; - -GethApiDouble.prototype.web3_clientVersion = function(callback) { - callback(null, "EthereumJS TestRPC/v" + pkg.version + "/ethereum-js") -}; - -GethApiDouble.prototype.web3_sha3 = function(string, callback) { - callback(null, to.hex(utils.sha3(string))); -}; - -GethApiDouble.prototype.net_version = function(callback) { - // net_version returns a string containing a base 10 integer. - callback(null, this.state.net_version + ""); -}; - -GethApiDouble.prototype.miner_start = function(threads, callback) { - if (!callback && typeof threads === 'function') { - callback = threads; - threads = null; - } - - this.state.startMining(function(err) { - callback(err, true); - }); -}; - -// indicate that `miner_start` only requires one argument (the callback) -GethApiDouble.prototype.miner_start.minLength = 1; - -GethApiDouble.prototype.miner_stop = function(callback) { - this.state.stopMining(function(err) { - callback(err, true); - }); -}; - -GethApiDouble.prototype.rpc_modules = function(callback) { - // returns the availible api modules and versions - callback(null, {"eth":"1.0","net":"1.0","rpc":"1.0","web3":"1.0","evm":"1.0","personal":"1.0"}); -}; - -GethApiDouble.prototype.personal_listAccounts = function(callback) { - callback(null, Object.keys(this.state.personal_accounts)); -}; - -GethApiDouble.prototype.personal_newAccount = function(password, callback) { - var account = this.state.createAccount({ generate: true }); - this.state.accounts[account.address.toLowerCase()] = account; - this.state.personal_accounts[account.address.toLowerCase()] = true; - this.state.account_passwords[account.address.toLowerCase()] = password; - callback(null, account.address); -}; - -GethApiDouble.prototype.personal_importRawKey = function(rawKey, password, callback) { - var account = this.state.createAccount({ secretKey: rawKey }); - this.state.accounts[account.address.toLowerCase()] = account; - this.state.personal_accounts[account.address.toLowerCase()] = true; - this.state.account_passwords[account.address.toLowerCase()] = password; - callback(null, account.address); -}; - -GethApiDouble.prototype.personal_lockAccount = function(address, callback) { - var account = this.state.personal_accounts[address.toLowerCase()]; - if (account !== true) { - return callback("Account not found"); - } - delete this.state.unlocked_accounts[address.toLowerCase()]; - callback(null, true); -}; - -GethApiDouble.prototype.personal_unlockAccount = function(address, password, duration, callback) { - // FIXME handle duration - var account = this.state.personal_accounts[address.toLowerCase()]; - if (account !== true) { - return callback("Account not found"); - } - - var storedPassword = this.state.account_passwords[address.toLowerCase()]; - if (storedPassword !== undefined && storedPassword !== password) { - return callback("Invalid password") - } - - this.state.unlocked_accounts[address.toLowerCase()] = true; - callback(null, true); -}; - -GethApiDouble.prototype.personal_sendTransaction = function(tx_data, password, callback) { - if (tx_data.from == null) { - callback("Sender not found"); - return; - } - - var from = utils.addHexPrefix(tx_data.from).toLowerCase(); - - var self = this; - self.personal_unlockAccount(from, password, null, function(err) { - if (err) return callback(err); - - self.state.queueTransaction("eth_sendTransaction", tx_data, null, function(err, ret) { - self.state.unlocked_accounts[from.toLowerCase()] = false; - callback(err, ret); - }); - }); -}; - -/* Functions for testing purposes only. */ - -GethApiDouble.prototype.evm_snapshot = function(callback) { - this.state.snapshot(callback) -}; - -GethApiDouble.prototype.evm_revert = function(snapshot_id, callback) { - this.state.revert(snapshot_id, callback); -}; - -GethApiDouble.prototype.evm_increaseTime = function(seconds, callback) { - callback(null, this.state.blockchain.increaseTime(seconds)); -}; - -GethApiDouble.prototype.evm_setTime = function(date, callback) { - callback(null, this.state.blockchain.setTime(date)) -}; - -GethApiDouble.prototype.evm_mine = function(timestamp, callback) { - var self = this; - if (typeof timestamp == "function") { - callback = timestamp; - timestamp = undefined; - } - this.state.processBlock(timestamp, function(err) { - if (err) return callback(err); - callback(err, '0x0'); - }); -}; - -// indicate that `evm_mine` only requires one argument (the callback) -GethApiDouble.prototype.evm_mine.minLength = 1; - -GethApiDouble.prototype.debug_traceTransaction = function(tx_hash, params, callback) { - if (typeof params == "function") { - callback = params; - params = []; - } - - this.state.queueTransactionTrace(tx_hash, params, callback); -}; - -/* - RPC AUDIT: - TODO ETH: eth_getUncleCountByBlockHash, eth_getUncleCountByBlockNumber, eth_getUncleByBlockHashAndIndex, - eth_getUncleByBlockNumberAndIndex, eth_getWork, eth_submitWork, eth_submitHashrate - - TODO DB: db_putString, db_getString, db_putHex, db_getHex - - TODO WHISPER: shh_post, shh_newIdentity, shh_hasIdentity, shh_newGroup, shh_addToGroup, - shh_newFilter, shh_uninstallFilter, shh_getFilterChanges, shh_getMessages -*/ - -/** - * Returns the number of uncles in a block from a block matching the given block hash. - * - * @param {DATA, 32 Bytes} hash - hash of a block. - * @callback callback - * @param {error} err - Error Object - * @param {QUANTITY} result - integer of the number of uncles in this block. - */ -GethApiDouble.prototype.eth_getUncleCountByBlockHash = function(hash, callback) { - callback(null, '0x0'); -}; - -/** - * Returns the number of uncles in a block from a block matching the given block number. - * - * @param {QUANTITY} blockNumber - integer of a block number, or the string "latest", "earliest" or "pending". Ex: '0xe8', // 232 - * @callback callback - * @param {error} err - Error Object - * @param {QUANTITY} result - integer of the number of uncles in this block. - */ -GethApiDouble.prototype.eth_getUncleCountByBlockNumber = function(blockNumber, callback) { - callback(null, '0x0'); -}; - -/** - * Returns information about a uncle of a block by hash and uncle index position. - * - * @param {DATA, 32 Bytes} hash - hash of a block - * @param {QUANTITY} index - the uncle's index position. - * @callback callback - * @param {error} err - Error Object - * @param {Object} result - A block object, - */ -GethApiDouble.prototype.eth_getUncleByBlockHashAndIndex = function(hash, index, callback) { - callback(null, {}); -}; - -/** - * Returns information about a uncle of a block by number and uncle index position. - * - * @param {QUANTITY} blockNumber - a block number, or the string "earliest", "latest" or "pending", as in the default block parameter. - * @param {QUANTITY} uncleIndex - the uncle's index position. - * @callback callback - * @param {error} err - Error object - * @param {Object} resutl - A block object, - */ -GethApiDouble.prototype.eth_getUncleByBlockNumberAndIndex = function(blockNumber, uncleIndex, callback) { - callback(null, {}); -}; - -/** - * Creates a filter in the node, to notify when new pending transactions arrive. - * - * @callback callback - * @param {error} err - Error object - * @param {QUANTITY} result - A filter id - */ -GethApiDouble.prototype.eth_newPendingTransactionFilter = function(callback) { - callback(null, '0x00'); -}; - -/** - * Returns an array of all logs matching filter with given id. - * - * @param {QUANTITY} filter_id - A filter id - * @callback callback - * @param {error} err - Error object - * @param {Array of Log Objects} result - More Info: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs - */ -GethApiDouble.prototype.eth_getFilterLogs = function(filter_id, callback) { - callback(null, []); -}; - -/** - * Returns: An Array with the following elements - * 1: DATA, 32 Bytes - current block header pow-hash - * 2: DATA, 32 Bytes - the seed hash used for the DAG. - * 3: DATA, 32 Bytes - the boundary condition ("target"), 2^256 / difficulty. - * - * @param {QUANTITY} filter_id - A filter id - * @callback callback - * @param {error} err - Error object - * @param {Array} result - the hash of the current block, the seedHash, and the boundary condition to be met ("target"). - */ -GethApiDouble.prototype.eth_getWork = function(filter_id, callback) { - callback(null, []); -}; - -/** - * Used for submitting a proof-of-work solution - * - * @param {DATA, 8 Bytes} nonce - The nonce found (64 bits) - * @param {DATA, 32 Bytes} powHash - The header's pow-hash (256 bits) - * @param {DATA, 32 Bytes} digest - The mix digest (256 bits) - * @callback callback - * @param {error} err - Error object - * @param {Boolean} result - returns true if the provided solution is valid, otherwise false. - */ -GethApiDouble.prototype.eth_submitWork = function(nonce, powHash, digest, callback) { - callback(null, false); -}; - -/** - * Used for submitting mining hashrate. - * - * @param {String} hashRate - a hexadecimal string representation (32 bytes) of the hash rate - * @param {String} clientID - A random hexadecimal(32 bytes) ID identifying the client - * @callback callback - * @param {error} err - Error object - * @param {Boolean} result - returns true if submitting went through succesfully and false otherwise. - */ -GethApiDouble.prototype.eth_submitHashrate = function(hashRate, clientID, callback) { - callback(null, false); -}; - - -/** - * Stores a string in the local database. - * - * @param {String} dbName - Database name. - * @param {String} key - Key name. - * @param {String} value - String to store. - * @callback callback - * @param {error} err - Error object - * @param {Boolean} result - returns true if the value was stored, otherwise false. - */ -GethApiDouble.prototype.db_putString = function(dbName, key, value, callback) { - callback(null, false); -}; - -/** - * Returns string from the local database - * - * @param {String} dbName - Database name. - * @param {String} key - Key name. - * @callback callback - * @param {error} - Error Object - * @param {String} result - The previously stored string. - */ -GethApiDouble.prototype.db_getString = function(dbName, key, callback) { - callback(null, ""); -}; - -/** - * Stores binary data in the local database. - * - * @param {String} dbName - Database name. - * @param {String} key - Key name. - * @param {DATA} data - Data to store. - * @callback callback - * @param {error} err - Error Object - * @param {Boolean} result - returns true if the value was stored, otherwise false. - */ -GethApiDouble.prototype.db_putHex = function(dbName, key, data, callback) { - callback(null, false); -}; - -/** - * Returns binary data from the local database - * - * @param {String} dbName - Database name. - * @param {String} key - Key name. - * @callback callback - * @param {error} err - Error Object - * @param {DATA} result - The previously stored data. - */ -GethApiDouble.prototype.db_getHex = function(dbName, key, callback) { - callback(null, "0x00"); -}; - - -/** - * Sends a whisper message. - * - * @param {DATA, 60 Bytes} from - (optional) The identity of the sender. - * @param {DATA, 60 Bytes} to - (optional) The identity of the receiver. When present whisper will encrypt the message so that only the receiver can decrypt it. - * @param {Array of DATA} topics - Array of DATA topics, for the receiver to identify messages. - * @param {DATA} payload - The payload of the message. - * @param {QUANTITY} priority - The integer of the priority in a range from ... (?). - * @param {QUANTITY} ttl - integer of the time to live in seconds. - * @callback callback - * @param {error} err - Error Object - * @param {Boolean} result - returns true if the message was sent, otherwise false. - */ -GethApiDouble.prototype.shh_post = function(from, to, topics, payload, priority, ttl, callback) { - callback(null, false); -}; - -/** - * Creates new whisper identity in the client. - * - * @callback callback - * @param {error} err - Error Object - * @param {DATA, 60 Bytes} result - the address of the new identiy. - */ -GethApiDouble.prototype.shh_newIdentity = function(callback) { - callback(null, '0x00'); -}; - -/** - * Checks if the client hold the private keys for a given identity. - * - * @param {DATA, 60 Bytes} address - The identity address to check. - * @callback callback - * @param {error} err - Error Object - * @param {Boolean} result - returns true if the client holds the privatekey for that identity, otherwise false. - */ -GethApiDouble.prototype.shh_hasIdentity = function(address, callback) { - callback(null, false); -}; - - -/** - * Creates a new group. - * - * @callback callback - * @param {error} err - Error Object - * @param {DATA, 60 Bytes} result - the address of the new group. - */ -GethApiDouble.prototype.shh_newGroup = function(callback) { - callback(null, '0x00'); -}; - -/** - * Adds a whisper identity to the group - * - * @param {DATA, 60 Bytes} - The identity address to add to a group. - * @callback callback - * @param {error} err - Error Object - * @param {Boolean} result - returns true if the identity was successfully added to the group, otherwise false. - */ -GethApiDouble.prototype.shh_addToGroup = function(address, callback) { - callback(null, false); -}; - - -/** - * Creates filter to notify, when client receives whisper message matching the filter options. - * - * @param {DATA, 60 Bytes} to - (optional) Identity of the receiver. When present it will try to decrypt any incoming message if the client holds the private key to this identity. - * @param {Array of DATA} topics - Array of DATA topics which the incoming message's topics should match. - * @callback callback - * @param {error} err - Error Object - * @param {Boolean} result - returns true if the identity was successfully added to the group, otherwise false. - */ -GethApiDouble.prototype.shh_newFilter = function(to, topics, callback) { - callback(null, false); -}; - -/** - * Uninstalls a filter with given id. Should always be called when watch is no longer needed. - * Additonally Filters timeout when they aren't requested with shh_getFilterChanges for a period of time. - * - * @param {QUANTITY} id - The filter id. Ex: "0x7" - * @callback callback - * @param {error} err - Error Object - * @param {Boolean} result - true if the filter was successfully uninstalled, otherwise false. - */ -GethApiDouble.prototype.shh_uninstallFilter = function(id, callback) { - callback(null, false); -}; - -/** - * Polling method for whisper filters. Returns new messages since the last call of this method. - * - * @param {QUANTITY} id - The filter id. Ex: "0x7" - * @callback callback - * @param {error} err - Error Object - * @param {Array} result - More Info: https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges - */ -GethApiDouble.prototype.shh_getFilterChanges = function(id, callback) { - callback(null, []); -}; - -/** - * Get all messages matching a filter. Unlike shh_getFilterChanges this returns all messages. - * - * @param {QUANTITY} id - The filter id. Ex: "0x7" - * @callback callback - * @param {error} err - Error Object - * @param {Array} result - See: shh_getFilterChanges - */ -GethApiDouble.prototype.shh_getMessages = function(id, callback) { - callback(null, false); -}; - - -module.exports = GethApiDouble; diff --git a/lib/subproviders/gethdefaults.js b/lib/subproviders/gethdefaults.js deleted file mode 100644 index 09e5756b7e..0000000000 --- a/lib/subproviders/gethdefaults.js +++ /dev/null @@ -1,36 +0,0 @@ -var Subprovider = require('web3-provider-engine/subproviders/subprovider.js'); -var inherits = require("util").inherits; - -inherits(GethDefaults, Subprovider); - -module.exports = GethDefaults; - -function GethDefaults() {}; - -// Massage eth_estimateGas requests, setting default data (e.g., from) if -// not specified. This is here specifically to make the testrpc -// react like Geth. -GethDefaults.prototype.handleRequest = function(payload, next, end) { - var self = this; - - if (payload.method != "eth_estimateGas" && payload.method != "eth_call") { - return next(); - } - - var params = payload.params[0]; - - if (params.from == null) { - this.emitPayload({ - method: "eth_coinbase" - }, function(err, result) { - if (err) return end(err); - - var coinbase = result.result; - - params.from = coinbase; - next(); - }); - } else { - next(); - } -}; diff --git a/lib/subproviders/reactiveblocktracker.js b/lib/subproviders/reactiveblocktracker.js deleted file mode 100644 index 0cb4b687e8..0000000000 --- a/lib/subproviders/reactiveblocktracker.js +++ /dev/null @@ -1,47 +0,0 @@ -var Subprovider = require('web3-provider-engine/subproviders/subprovider.js'); -var inherits = require("util").inherits; - -inherits(ReactiveBlockTracker, Subprovider); - -module.exports = ReactiveBlockTracker; - -function ReactiveBlockTracker() { - this.methods = { - "eth_call": "before", - "eth_getStorageAt": "before", - "eth_getLogs": "before" - }; -}; - -// Fetch the block before certain requests to make sure we're completely updated -// before those methods are processed. Also, fetch the block after certain requests -// to speed things up. -ReactiveBlockTracker.prototype.handleRequest = function(payload, next, end) { - var self = this; - - var when = this.methods[payload.method]; - - if (when == null) { - return next(); - } - - function fetchBlock(cb) { - self.engine.fetchBlock("latest", function(err, block) { - if (err) return end(err); - if (!self.engine.currentBlock || 0 !== self.engine.currentBlock.hash.compare(block.hash)) { - self.engine._setCurrentBlock(block); - } - cb(); - }); - } - - if (when == "before") { - fetchBlock(function() { - next(); - }); - } else { - next(function(error, result, cb) { - fetchBlock(cb); - }); - } -}; diff --git a/lib/subproviders/requestfunnel.js b/lib/subproviders/requestfunnel.js deleted file mode 100644 index 3022a8a3e9..0000000000 --- a/lib/subproviders/requestfunnel.js +++ /dev/null @@ -1,60 +0,0 @@ -var Subprovider = require('web3-provider-engine/subproviders/subprovider.js'); -var inherits = require("util").inherits; - -inherits(RequestFunnel, Subprovider); - -module.exports = RequestFunnel; - -// See if any payloads for the specified methods are marked as external. -// If they are external, and match the method list, process them one at -// a time. -function RequestFunnel() { - // We use an object here for O(1) lookups (speed). - this.methods = { - "eth_call": true, - "eth_getStorageAt": true, - "eth_sendTransaction": true, - "eth_sendRawTransaction": true, - - // Ensure block filter and filter changes are process one at a time - // as well so filter requests that come in after a transaction get - // processed once that transaction has finished processing. - "eth_newBlockFilter": true, - "eth_getFilterChanges": true, - "eth_getFilterLogs": true - }; - this.queue = []; - this.isWorking = false; -}; - -RequestFunnel.prototype.handleRequest = function(payload, next, end) { - if (payload.external != true || this.methods[payload.method] != true) { - return next(); - } - - this.queue.push([payload, next]); - - if (this.isWorking == false) { - this.processNext(); - } -}; - -RequestFunnel.prototype.processNext = function() { - var self = this; - - if (this.queue.length == 0) { - this.isWorking = false; - return; - } - - this.isWorking = true; - - var item = this.queue.shift(); - var payload = item[0]; - var next = item[1]; - - next(function(error, request, cb) { - cb(); - self.processNext(); - }); -}; diff --git a/lib/utils/block_helper.js b/lib/utils/block_helper.js deleted file mode 100644 index e7f99f746a..0000000000 --- a/lib/utils/block_helper.js +++ /dev/null @@ -1,35 +0,0 @@ -var to = require("./to"); -var txhelper = require("./txhelper") - -module.exports = { - toJSON: function(block, include_full_transactions) { - return { - number: to.rpcQuantityHexString(block.header.number), - hash: to.hex(block.hash()), - parentHash: to.hex(block.header.parentHash), //common.hash - mixHash: to.hex(block.header.mixHash), - nonce: to.rpcDataHexString(to.hex(block.header.nonce), 16), - sha3Uncles: to.hex(block.header.uncleHash), - logsBloom: to.hex(block.header.bloom), - transactionsRoot: to.hex(block.header.transactionsTrie), - stateRoot: to.hex(block.header.stateRoot), - receiptsRoot: to.hex(block.header.receiptTrie), - miner: to.hex(block.header.coinbase), - difficulty: to.rpcQuantityHexString(block.header.difficulty), - totalDifficulty: to.rpcQuantityHexString(block.header.difficulty), // TODO: Figure out what to do here. - extraData: to.rpcDataHexString(block.header.extraData), - size: to.hex(1000), // TODO: Do something better here - gasLimit: to.rpcQuantityHexString(block.header.gasLimit), - gasUsed: to.rpcQuantityHexString(block.header.gasUsed), - timestamp: to.rpcQuantityHexString(block.header.timestamp), - transactions: block.transactions.map(function(tx) { - if (include_full_transactions) { - return txhelper.toJSON(tx, block); - } else { - return to.hex(tx.hash()); - } - }), - uncles: []//block.uncleHeaders.map(function(uncleHash) {return to.hex(uncleHash)}) - } - } -} diff --git a/lib/utils/forkedblockchain.js b/lib/utils/forkedblockchain.js deleted file mode 100644 index 20ff259969..0000000000 --- a/lib/utils/forkedblockchain.js +++ /dev/null @@ -1,601 +0,0 @@ -var BlockchainDouble = require("../blockchain_double.js"); -var VM = require("ethereumjs-vm"); -var Account = require("ethereumjs-account"); -var Block = require("ethereumjs-block"); -var Log = require("./log.js"); -var Receipt = require("./receipt.js"); -var utils = require("ethereumjs-util"); -var ForkedStorageTrie = require("./forkedstoragetrie.js"); -var Web3 = require("web3"); -var to = require("./to.js"); -var async = require("async"); -var txhelper = require("./txhelper.js") -var BN = require("bn.js"); - -var inherits = require("util").inherits; - -inherits(ForkedBlockchain, BlockchainDouble); - -function ForkedBlockchain(options) { - var self = this; - - this.options = options || {} - - if (options.fork == null) { - throw new Error("ForkedBlockchain must be passed a fork parameter."); - } - - this.fork = options.fork; - this.fork_block_number = options.fork_block_number; - this.fork_version = null; - - if (typeof this.fork == "string") { - if (this.fork.indexOf("@") >= 0) { - var split = this.fork.split("@"); - this.fork = split[0]; - this.fork_block_number = parseInt(split[1]); - } - - this.fork = new Web3.providers.HttpProvider(this.fork); - } - - this.time = options.time; - this.storageTrieCache = {}; - - BlockchainDouble.call(this, options); - - this.web3 = new Web3(this.fork); -}; - -ForkedBlockchain.prototype.initialize = function(accounts, callback) { - var self = this; - - this.web3.eth.net.getId(function(err, version) { - if (err) return callback(err); - - self.fork_version = version; - - BlockchainDouble.prototype.initialize.call(self, accounts, function(err) { - if (err) return callback(err); - - // Unfortunately forking requires a bit of monkey patching, but it gets the job done. - self.vm.stateManager._lookupStorageTrie = self.lookupStorageTrie.bind(self); - self.vm.stateManager.cache._lookupAccount = self.getAccount.bind(self); - self.vm.stateManager.getContractCode = self.getCode.bind(self); - self.vm.stateManager.putContractCode = self.putCode.bind(self); - - callback(); - }); - }); -}; - -ForkedBlockchain.prototype.createStateTrie = function(db, root) { - return new ForkedStorageTrie(db, root, { - fork: this.fork, - fork_block_number: this.fork_block_number, - blockchain: this - }); -}; - -ForkedBlockchain.prototype.createGenesisBlock = function(callback) { - var self = this; - var blockNumber = this.fork_block_number || "latest"; - - self.web3.eth.getBlock(blockNumber, function(err, json) { - if (err) return callback(err); - - // If no start time was passed, set the time to where we forked from. - // We only want to do this if a block was explicitly passed. If a block - // number wasn't passed, then we're using the last block and the current time. - if (!self.time && self.fork_block_number) { - self.time = self.options.time = new Date(to.number(json.timestamp) * 1000); - self.setTime(self.time); - } - - blockNumber = to.hex(json.number); - - // Update the relevant block numbers - self.fork_block_number = self.options.fork_block_number = blockNumber; - self.stateTrie.fork_block_number = blockNumber; - - self.createBlock(function(err, block) { - if (err) return callback(err); - - block.header.number = utils.toBuffer(to.number(json.number) + 1); - block.header.parentHash = utils.toBuffer(json.hash); - - callback(null, block); - }); - }); -}; - -ForkedBlockchain.prototype.createForkedStorageTrie = function(address) { - address = to.hex(address); - - var trie = new ForkedStorageTrie(this.data.trie_db, null, { - address: address, - stateTrie: this.stateTrie, - blockchain: this, - fork: this.fork, - fork_block_number: this.fork_block_number - }); - - this.storageTrieCache[address] = trie; - - return trie; -}; - -ForkedBlockchain.prototype.lookupStorageTrie = function(address, callback) { - var self = this - - address = to.hex(address); - - if (this.storageTrieCache[address] != null) { - return callback(null, this.storageTrieCache[address]); - } - - callback(null, this.createForkedStorageTrie(address)); -}; - -ForkedBlockchain.prototype.isFallbackBlock = function(value, callback) { - var self = this; - - self.getEffectiveBlockNumber(value, function(err, number) { - if (err) return callback(err); - - callback(null, number <= to.number(self.fork_block_number)); - }); -}; - -ForkedBlockchain.prototype.isBlockHash = function(value) { - return typeof value == "string" && value.indexOf("0x") == 0 && value.length > 42; -} - -ForkedBlockchain.prototype.isFallbackBlockHash = function(value, callback) { - var self = this; - - if (!this.isBlockHash(value)) { - return callback(null, false); - } - - self.data.blockHashes.get(value, function(err, blockIndex) { - if (err) { - if (err.notFound) { - // If the block isn't found in our database, then it must be a fallback block. - return callback(null, true); - } else { - return callback(err); - } - } - callback(null, false); - }); -} - -ForkedBlockchain.prototype.getFallbackBlock = function(number_or_hash, cb) { - var self = this; - - // This function sometimes gets passed hex values that aren't long enough to - // be a block hash. In that case, let's convert them to a big number so Web3 - // doesn't get stopped up. - if (typeof number_or_hash == "string" && number_or_hash.length < 66) { - number_or_hash = self.web3.utils.toBN(number_or_hash) - } - - self.web3.eth.getBlock(number_or_hash, true, function(err, json) { - if (err) return cb(err); - - if (json == null) return cb(); - - var block = new Block(); - - block.header.parentHash = utils.toBuffer(json.parentHash); - block.header.uncleHash = utils.toBuffer(json.sha3Uncles); - block.header.coinbase = utils.toBuffer(json.miner); - block.header.stateRoot = utils.toBuffer(json.stateRoot); // Should we include the following three? - block.header.transactionTrie = utils.toBuffer(json.transactionsRoot); - block.header.receiptTrie = utils.toBuffer(json.receiptsRoot); - block.header.bloom = utils.toBuffer(json.logsBloom); - block.header.difficulty = utils.toBuffer("0x" + json.totalDifficulty.toString(16)); // BigNumber - block.header.number = utils.toBuffer(json.number); - block.header.gasLimit = utils.toBuffer(json.gasLimit); - block.header.gasUsed = utils.toBuffer(json.gasUsed); - block.header.timestamp = utils.toBuffer(json.timestamp); - block.header.extraData = utils.toBuffer(json.extraData); - - (json.transactions || []).forEach(function(tx_json, index) { - block.transactions.push(txhelper.fromJSON(tx_json)); - }); - - // Fake block. Let's do the worst. - // TODO: Attempt to fill out all block data so as to produce the same hash! (can we?) - block.hash = function() { - return utils.toBuffer(json.hash); - } - - cb(null, block); - }); -} - - -ForkedBlockchain.prototype.getBlock = function(number, callback) { - var self = this; - - this.isFallbackBlockHash(number, function(err, isFallbackBlockHash) { - if (err) return callback(err); - if (isFallbackBlockHash) { - return self.getFallbackBlock(number, callback); - } - - self.isFallbackBlock(number, function(err, isFallbackBlock) { - if (err) return callback(err); - - if (isFallbackBlock) { - return self.getFallbackBlock(number, callback); - } - - // If we don't have string-based a block hash, turn what we do have into a number - // before sending it to getBlock. - function getBlockReference(value, callback) { - if (!self.isBlockHash(value)) { - self.getRelativeBlockNumber(value, callback); - } else { - callback(null, value); - } - } - - getBlockReference(number, function(err, blockReference) { - if (err) return callback(err); - - BlockchainDouble.prototype.getBlock.call(self, blockReference, callback); - }); - }); - }); -}; - -ForkedBlockchain.prototype.getStorage = function(address, key, number, callback) { - this.lookupStorageTrie(address, function(err, trie) { - if (err) return callback(err); - trie.get(key, callback); - }); -}; - -ForkedBlockchain.prototype.getCode = function(address, number, callback) { - var self = this; - - if (typeof number == "function") { - callback = number; - number = "latest"; - } - - if (!number) { - number = "latest"; - } - - this.getEffectiveBlockNumber(number, function(err, effective) { - number = effective; - - self.stateTrie.keyExists(address, function(err, exists) { - // If we've stored the value and we're looking at one of our stored blocks, - // get it from our stored data. - if (exists && number > to.number(self.fork_block_number)) { - BlockchainDouble.prototype.getCode.call(self, address, number, callback); - } else { - - // Else, we need to fetch it from web3. If our number is greater than - // the fork, let's just use "latest". - if (number > to.number(self.fork_block_number)) { - number = "latest"; - } - - self.fetchCodeFromFallback(address, number, function(err, code) { - if (code) { - code = utils.toBuffer(code); - } - callback(err, code); - }); - } - }); - }); -}; - -ForkedBlockchain.prototype.putCode = function(address, value, callback) { - // This is a bit of a hack. We need to bypass the vm's - // _lookupAccount call that vm.stateManager.putContractCode() uses. - // This means we have to do some things ourself. The last call - // to self.stateTrie.put() at the bottom is important because - // we can't just be satisfied putting it in the cache. - - var self = this; - self.vm.stateManager.cache.flush(() => { - address = utils.toBuffer(address); - this.stateTrie.get(address, function(err, data) { - if (err) return callback(err); - - var account = new Account(data); - account.setCode(self.stateTrie, value, function(err, result) { - if (err) return callback(err); - - self.stateTrie.put(address, account.serialize(), function(err) { - if (err) return callback(err); - - // Ensure the cache updates as well. - self.vm.stateManager.putAccount(address, account, callback); - }); - }); - }) - }); -}; - -ForkedBlockchain.prototype.getAccount = function(address, number, callback) { - var self = this; - - if (typeof number == "function") { - callback = number; - number = "latest"; - } - - this.getEffectiveBlockNumber(number, function(err, effective) { - if (err) return callback(err); - number = effective; - - // If the account doesn't exist in our state trie, get it off the wire. - self.stateTrie.keyExists(address, function(err, exists) { - if (err) return callback(err); - - if (exists && number > to.number(self.fork_block_number)) { - BlockchainDouble.prototype.getAccount.call(self, address, number, function(err, acc) { - if (err) return callback(err); - callback(null, acc); - }); - } else { - self.fetchAccountFromFallback(address, number, callback); - } - }); - }); -}; - -ForkedBlockchain.prototype.getTransaction = function(hash, callback) { - var self = this; - BlockchainDouble.prototype.getTransaction.call(this, hash, function(err, tx) { - if (err) return callback(err); - if (tx != null) return callback(null, tx); - - self.web3.eth.getTransaction(hash, function(err, result) { - if (err) return callback(err); - - if (result) { - result = txhelper.fromJSON(result); - } - - callback(null, result); - }); - }); -}; - -ForkedBlockchain.prototype.getTransactionReceipt = function(hash, callback) { - var self = this; - BlockchainDouble.prototype.getTransactionReceipt.call(this, hash, function(err, receipt) { - if (err) return callback(err); - if (receipt) return callback(null, receipt); - - self.web3.eth.getTransactionReceipt(hash, function(err, receipt_json) { - if (err) return callback(err); - if (!receipt_json) return callback(); - - async.parallel({ - tx: self.getTransaction.bind(self, hash), - block: self.getBlock.bind(self, receipt_json.blockNumber) - }, function(err, result) { - if (err) return callback(err); - - var logs = receipt_json.logs.map(function(log) { - return new Log(log); - }); - var receipt = new Receipt(result.tx, result.block, logs, receipt_json.gasUsed, receipt_json.cumulativeGasUsed, - receipt_json.contractAddress, receipt_json.status, to.hex(receipt_json.logsBloom)); - - callback(null, receipt); - }); - }); - }); -}; - -ForkedBlockchain.prototype.fetchAccountFromFallback = function(address, block_number, callback) { - var self = this; - address = to.hex(address); - - async.parallel({ - code: this.fetchCodeFromFallback.bind(this, address, block_number), - balance: this.fetchBalanceFromFallback.bind(this, address, block_number), - nonce: this.fetchNonceFromFallback.bind(this, address, block_number) - }, function(err, results) { - if (err) return callback(err); - - var code = results.code; - var balance = results.balance; - var nonce = results.nonce; - - var account = new Account({ - nonce: nonce, - balance: balance - }); - - account.exists = code != "0x0" || balance != "0x0" || nonce != "0x0"; - - // This puts the code on the trie, keyed by the hash of the code. - // It does not actually link an account to code in the trie. - account.setCode(self.stateTrie, utils.toBuffer(code), function(err) { - if (err) return callback(err); - callback(null, account); - }); - }); -}; - -ForkedBlockchain.prototype.fetchCodeFromFallback = function(address, block_number, callback) { - var self = this; - address = to.hex(address); - - // Allow an optional block_number - if (typeof block_number == "function") { - callback = block_number; - block_number = this.fork_block_number; - } - - this.getSafeFallbackBlockNumber(block_number, function(err, safe_block_number) { - if (err) return callback(err); - - self.web3.eth.getCode(address, safe_block_number, function(err, code) { - if (err) return callback(err); - - code = "0x" + utils.toBuffer(code).toString("hex"); - callback(null, code); - }); - }); -} - -ForkedBlockchain.prototype.fetchBalanceFromFallback = function(address, block_number, callback) { - var self = this; - address = to.hex(address); - - // Allow an optional block_number - if (typeof block_number == "function") { - callback = block_number; - block_number = this.fork_block_number; - } - - this.getSafeFallbackBlockNumber(block_number, function(err, safe_block_number) { - if (err) return callback(err); - - self.web3.eth.getBalance(address, safe_block_number, function(err, balance) { - if (err) return callback(err); - - balance = "0x" + new BN(balance).toString(16); - callback(null, balance); - }); - }); -} - -ForkedBlockchain.prototype.fetchNonceFromFallback = function(address, block_number, callback) { - var self = this; - address = to.hex(address); - - // Allow an optional block_number - if (typeof block_number == "function") { - callback = block_number; - block_number = this.fork_block_number; - } - - this.getSafeFallbackBlockNumber(block_number, function(err, safe_block_number) { - if (err) return callback(err); - - self.web3.eth.getTransactionCount(address, safe_block_number, function(err, nonce) { - if (err) return callback(err); - - nonce = "0x" + self.web3.utils.toBN(nonce).toString(16); - callback(null, nonce); - }); - }); -} - -ForkedBlockchain.prototype.getHeight = function(callback) { - var self = this; - this.latestBlock(function(err, block) { - if (err) return callback(err); - callback(null, to.number(block.header.number)); - }); -}; - -ForkedBlockchain.prototype.getRelativeBlockNumber = function(number, callback) { - var self = this; - this.getEffectiveBlockNumber(number, function(err, effective) { - if (err) return callback(err); - callback(null, effective - to.number(self.fork_block_number) - 1) - }); -}; - -ForkedBlockchain.prototype.getSafeFallbackBlockNumber = function(block_number, callback) { - var fork_block_number = to.number(this.fork_block_number); - - if (block_number == null) { - return callback(null, fork_block_number); - }; - - this.getEffectiveBlockNumber(block_number, function(err, effective) { - if (effective > fork_block_number) { - effective = fork_block_number - } - - callback(null, effective); - }); -}; - -ForkedBlockchain.prototype.getBlockLogs = function(number, callback) { - var self = this; - - this.getEffectiveBlockNumber(number, function(err, effective) { - if (err) return callback(err); - - self.getRelativeBlockNumber(effective, function(err, relative) { - if (err) return callback(err); - - if (relative < 0) { - self.getBlock(number, function(err, block) { - if (err) return callback(err); - - self.web3.currentProvider.send({ - jsonrpc: "2.0", - method: "eth_getLogs", - params: [{ - fromBlock: to.hex(number), - toBlock: to.hex(number) - }], - id: new Date().getTime() - }, function(err, res) { - if (err) return callback(err); - - var logs = res.result.map(function(log) { - // To make this result masquerade as the right information. - log.block = block; - return new Log(log); - }); - - callback(null, logs); - }); - }); - } else { - BlockchainDouble.prototype.getBlockLogs.call(self, relative, callback); - } - }); - }); -}; - -ForkedBlockchain.prototype._checkpointTrie = function() { - var self = this; - - BlockchainDouble.prototype._checkpointTrie.call(this); - - Object.keys(this.storageTrieCache).forEach(function(address) { - var trie = self.storageTrieCache[address]; - trie.customCheckpoint(); - }); -}; - -ForkedBlockchain.prototype._revertTrie = function() { - var self = this; - - BlockchainDouble.prototype._revertTrie.call(this); - - Object.keys(this.storageTrieCache).forEach(function(address) { - var trie = self.storageTrieCache[address]; - - // We're trying to revert to a point before this trie was created. - // Let's just remove the trie. - if (trie.checkpoints.length == 0) { - delete self.storageTrieCache[address]; - } else { - trie.customRevert(); - } - }); -}; - -module.exports = ForkedBlockchain; diff --git a/lib/utils/forkedstoragetrie.js b/lib/utils/forkedstoragetrie.js deleted file mode 100644 index 7d22d1b962..0000000000 --- a/lib/utils/forkedstoragetrie.js +++ /dev/null @@ -1,96 +0,0 @@ -var MerklePatriciaTree = require("merkle-patricia-tree"); -var Account = require("ethereumjs-account"); -var utils = require('ethereumjs-util') -var inherits = require("util").inherits; -var Web3 = require("web3"); -var to = require("./to.js"); -var async = require("async"); - -inherits(ForkedStorageTrie, MerklePatriciaTree) - -function ForkedStorageTrie(db, root, options) { - MerklePatriciaTree.call(this, db, root); - - this.address = options.address; - - this.fork = options.fork; - this.fork_block_number = options.fork_block_number; - - this.blockchain = options.blockchain; - - this.web3 = new Web3(); - this.web3.setProvider(this.fork); - - this.checkpoints = []; -} - -ForkedStorageTrie.prototype.keyExists = function(key, callback) { - key = utils.toBuffer(key); - - this.findPath(key, function (err, node, remainder, stack) { - var exists = false; - if (node && remainder.length === 0) { - exists = true; - } - callback(err, exists) - }) -}; - -// Note: This overrides a standard method whereas the other methods do not. -ForkedStorageTrie.prototype.get = function(key, block_number, callback) { - var self = this; - - // Allow an optional block_number - if (typeof block_number == "function") { - callback = block_number; - block_number = self.fork_block_number; - } - - // For geth; https://github.com/ethereumjs/ethereumjs-util/issues/79 - block_number = to.rpcQuantityHexString(block_number); - - key = utils.toBuffer(key); - - // If the account doesn't exist in our state trie, get it off the wire. - this.keyExists(key, function(err, exists) { - if (err) return callback(err); - - if (exists) { - MerklePatriciaTree.prototype.get.call(self, key, function(err, r) { - callback(err, r); - }); - } else { - // If this is the main trie, get the whole account. - if (self.address == null) { - self.blockchain.fetchAccountFromFallback(key, block_number, function(err, account) { - if (err) return callback(err); - - callback(null, account.serialize()); - }); - } else { - self.web3.eth.getStorageAt(to.hex(self.address), to.hex(key), block_number, function(err, value) { - if (err) return callback(err); - - value = utils.toBuffer(value); - value = utils.rlp.encode(value); - - callback(null, value); - }); - } - } - }); -}; - -// I don't want checkpoints to be removed by commits. -// Note: For some reason, naming this function checkpoint() -// -- overriding the default function -- prevents it from -// being called. -ForkedStorageTrie.prototype.customCheckpoint = function() { - this.checkpoints.push(this.root); -}; - -ForkedStorageTrie.prototype.customRevert = function() { - this.root = this.checkpoints.pop(); -}; - -module.exports = ForkedStorageTrie; diff --git a/lib/utils/log.js b/lib/utils/log.js deleted file mode 100644 index d1f803d32e..0000000000 --- a/lib/utils/log.js +++ /dev/null @@ -1,38 +0,0 @@ -var to = require("./to.js"); - -// Expects: -// -// logIndex: ... -// transactionIndex: ... -// transactionHash: ... -// block: ... -// address: ... -// data: ... -// topics: ... -// type: ... - -function Log(data) { - var self = this; - Object.keys(data).forEach(function(key) { - self[key] = data[key]; - }); -} - -Log.prototype.toJSON = function() { - // RPC quantity values like this.transactionIndex can be set to "0x00", - // use the explicit rpcQuantityHexString to properly format the JSON, removing leading zeroes. - // See RPC log format spec: https://github.com/ethereum/wiki/wiki/JSON-RPC - return { - logIndex: to.rpcQuantityHexString(this.logIndex), - transactionIndex: to.rpcQuantityHexString(this.transactionIndex), - transactionHash: to.rpcDataHexString(this.transactionHash), - blockHash: to.rpcDataHexString(this.block.hash()), - blockNumber: to.rpcQuantityHexString(this.block.header.number), - address: to.rpcDataHexString(this.address), - data: to.rpcDataHexString(this.data), - topics: this.topics, - type: "mined" - }; -}; - -module.exports = Log; diff --git a/lib/utils/random.js b/lib/utils/random.js deleted file mode 100644 index 893c81ebbc..0000000000 --- a/lib/utils/random.js +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - // Mimics crypto.random bytes, but takes in a random number generator - // as its second parameter. rng is expected to be a function that takes - // no parameters and returns a result like Math.random(). - // This is important because it allows for a seeded random number generator. - // Since this is a mock RPC library, the rng doesn't need to be cryptographically secure. - randomBytes: function(length, rng) { - var buf = []; - - for (var i = 0; i < length; i++) { - buf.push(rng()*255); - } - - return Buffer.from(buf); - }, - - randomAlphaNumericString: function(length, rng) { - const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - let text = ''; - - for (var i = 0; i < length; i++) { - text += alphabet.charAt(Math.floor((rng || Math.random)() * alphabet.length)); - } - - return text; - } - -} diff --git a/lib/utils/receipt.js b/lib/utils/receipt.js deleted file mode 100644 index 47061e3492..0000000000 --- a/lib/utils/receipt.js +++ /dev/null @@ -1,46 +0,0 @@ -var to = require("./to"); - -function Receipt(tx, block, logs, gasUsed, cumulativeGasUsed, contractAddress, status, logsBloom) { - this.tx = tx; - this.block = block; - this.logs = logs; - this.gasUsed = gasUsed; - this.cumulativeGasUsed = cumulativeGasUsed; - this.contractAddress = contractAddress; - this.status = status; - this.logsBloom = logsBloom; - - - this.transactionIndex = 0; - - for (var i = 0; i < block.transactions.length; i++) { - var current = block.transactions[i]; - if (current.hash().equals(tx.hash())) { - this.transactionIndex = i; - break; - } - } -} - -Receipt.prototype.toJSON = function() { - if (this.data != null) return data; - - // Enforce Hex formatting as defined in the RPC spec. - return { - transactionHash: to.rpcDataHexString(this.tx.hash()), - transactionIndex: to.rpcQuantityHexString(this.transactionIndex), - blockHash: to.rpcDataHexString(this.block.hash()), - blockNumber: to.rpcQuantityHexString(this.block.header.number), - gasUsed: to.rpcQuantityHexString(this.gasUsed), - cumulativeGasUsed: to.rpcQuantityHexString(this.cumulativeGasUsed), - contractAddress: this.contractAddress != null ? to.rpcDataHexString(this.contractAddress) : null, - logs: this.logs.map(function(log) {return log.toJSON()}), - status: to.rpcQuantityHexString(this.status), - logsBloom: to.rpcDataHexString(this.logsBloom), - v: to.rpcDataHexString(this.tx.v), - r: to.rpcDataHexString(this.tx.r), - s: to.rpcDataHexString(this.tx.s) - } -}; - -module.exports = Receipt; diff --git a/lib/utils/runtimeerror.js b/lib/utils/runtimeerror.js deleted file mode 100644 index 1ebbef303c..0000000000 --- a/lib/utils/runtimeerror.js +++ /dev/null @@ -1,100 +0,0 @@ -var inherits = require("util").inherits; -var to = require("./to"); -var abi = require("ethereumjs-abi"); - -inherits(RuntimeError, Error); - -// Note: ethereumjs-vm will return an object that has a "results" and "receipts" keys. -// You should pass in the whole object. -function RuntimeError(transactions, vm_output) { - - // Why not just Error.apply(this, [message])? See - // https://gist.github.com/justmoon/15511f92e5216fa2624b#anti-patterns - Error.captureStackTrace(this, this.constructor) - this.name = this.constructor.name; - - this.results = {}; - this.hashes = []; - - // handles creating this.message - this.combine(transactions, vm_output); -}; - -RuntimeError.prototype.combine = function(transactions, vm_output) { - // Can be combined with vm_output or another RuntimeError. - if (transactions instanceof RuntimeError) { - var err = transactions; - var keys = Object.keys(err.results); - - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - this.results[key] = err.results[key]; - Array.prototype.push.apply(this.hashes, err.hashes); - } - } else { - var results = vm_output.results; - - for (var i = 0; i < transactions.length; i++) { - var tx = transactions[i]; - var result = results[i]; - - // 1 means no error, oddly. - if (result.vm.exception != 1) { - var hash = to.hex(tx.hash()); - - this.hashes.push(hash); - var reason = undefined; - var returnData = result.vm.return; - if (returnData && returnData.slice(0, 4).toString("hex") === "08c379a0") { - reason = abi.rawDecode(["string"], returnData.slice(4))[0]; - } - - this.results[hash] = { - error: result.vm.exceptionError.error || result.vm.exceptionError, - program_counter: result.vm.runState.programCounter, - return: to.hex(result.vm.return), - reason: reason - }; - } - } - } - - // Once combined, set the message - if (this.hashes.length == 1) { - var exceptionResult = this.results[this.hashes[0]]; - var message = "VM Exception while processing transaction: " + exceptionResult.error; - if (exceptionResult.reason) { - message += " " + exceptionResult.reason; - } - this.message = message; - } else { - var message = "Multiple VM Exceptions while processing transactions: \n\n"; - - for (var i = 0; i < this.hashes.length; i++) { - var hash = this.hashes[i]; - var exceptionResult = this.results[hash]; - message += hash + ": " + exceptionResult.error; - if (exceptionResult.reason) { - message += " " + exceptionResult.reason; - } - message += "\n"; - } - this.message = message; - } -}; - -RuntimeError.prototype.count = function() { - return Object.keys(this.results).length; -}; - -RuntimeError.fromResults = function(transactions, vm_output) { - var err = new RuntimeError(transactions, vm_output); - - if (err.count() == 0) { - return null; - } - - return err; -}; - -module.exports = RuntimeError; diff --git a/lib/utils/to.js b/lib/utils/to.js deleted file mode 100644 index 1861795def..0000000000 --- a/lib/utils/to.js +++ /dev/null @@ -1,80 +0,0 @@ -var utils = require("ethereumjs-util"); - -module.exports = { - // Note: Do not use to.hex() when you really mean utils.addHexPrefix(). - hex: function(val) { - if (typeof val == "string") { - if (val.indexOf("0x") == 0) { - return val; - } else { - val = new utils.BN(val); - } - } - - if (typeof val == "boolean") { - val = val ? 1 : 0; - } - - if (typeof val == "number") { - val = utils.intToHex(val); - } - - // Support Buffer, BigInteger and BN library - // Hint: BN is used in ethereumjs - if (typeof val == "object") { - val = val.toString("hex"); - } - - return utils.addHexPrefix(val); - }, - - rpcQuantityHexString: function(val) { - val = this.hex(val); - val = "0x" + val.replace("0x", "").replace(/^0+/, ""); - - if (val == "0x") { - val = "0x0"; - } - - return val; - }, - - rpcDataHexString: function(val, length) { - if(typeof(length) == "number") { - val = this.hex(val).replace("0x", ""); - - val = new Array(length-val.length).fill("0").join("") + val; - } else { - if(val.length == 0) { - return "0x"; - } - val = this.hex(val).replace("0x", ""); - - if(val.length % 2 != 0) { - val = "0" + val; - } - } - return "0x" + val; - }, - - hexWithZeroPadding: function(val) { - val = this.hex(val); - const digits = val.replace("0x", ""); - if (digits.length & 0x1) { - return "0x0" + digits; - } - return val; - }, - - number: function(val) { - if (typeof val == "number") { - return val; - } - if (typeof val == "string") { - if (val.indexOf('0x') != 0) { - return parseInt(val) - } - } - return utils.bufferToInt(utils.toBuffer(val)); - } -}; diff --git a/lib/utils/txhelper.js b/lib/utils/txhelper.js deleted file mode 100644 index b90d6272de..0000000000 --- a/lib/utils/txhelper.js +++ /dev/null @@ -1,68 +0,0 @@ -var to = require("./to"); -var FakeTransaction = require('ethereumjs-tx/fake.js'); -var utils = require("ethereumjs-util"); - -module.exports = { - toJSON: function(tx, block) { - var transactionIndex = 0 - for (var i = 0; i < block.transactions.length; i++) { - var current = block.transactions[i]; - if (current.hash().equals(tx.hash())) { - transactionIndex = i; - break; - } - } - var resultJSON = { - hash: to.rpcDataHexString(tx.hash()), - nonce: to.rpcQuantityHexString(tx.nonce), - blockHash: to.rpcDataHexString(block.hash()), - blockNumber: to.rpcQuantityHexString(block.header.number), - transactionIndex: to.rpcQuantityHexString(transactionIndex), - from: to.rpcDataHexString(tx.from), - to: to.rpcDataHexString(tx.to), - value: to.rpcQuantityHexString(tx.value), - gas: to.rpcQuantityHexString(tx.gasLimit), - gasPrice: to.rpcQuantityHexString(tx.gasPrice), - input: to.rpcDataHexString(tx.data), - }; - - if (tx.v && tx.v.length > 0 && - tx.r && tx.r.length > 0 && - tx.s && tx.s.length > 0) { - resultJSON.v = to.hex(tx.v); - resultJSON.r = to.hex(tx.r); - resultJSON.s = to.hex(tx.s); - } - - return resultJSON; - }, - - fromJSON: function(json) { - var tx = new FakeTransaction({ - nonce: utils.toBuffer(to.hex(json.nonce)), - from: utils.toBuffer(to.hex(json.from)), - value: utils.toBuffer(to.hex(json.value)), - gasLimit: utils.toBuffer(to.hex(json.gas)), - gasPrice: utils.toBuffer(to.hex(json.gasPrice)), - data: utils.toBuffer(to.hex(json.input)) - }); - - if (json.v && json.v.length > 0 && - json.r && json.r.length > 0 && - json.s && json.s.length > 0) { - tx.v = utils.toBuffer(to.hex(json.v)); - tx.r = utils.toBuffer(to.hex(json.r)); - tx.s = utils.toBuffer(to.hex(json.s)); - } - - if (json.to) { - // Remove all padding and make it easily comparible. - var buf = utils.toBuffer(to.hex(json.to)); - if (!buf.equals(utils.toBuffer('0x0'))) { - tx.to = utils.setLengthLeft(buf, 20); - } - } - - return tx; - } -}; diff --git a/lib/utils/txrejectederror.js b/lib/utils/txrejectederror.js deleted file mode 100644 index 270b20c081..0000000000 --- a/lib/utils/txrejectederror.js +++ /dev/null @@ -1,15 +0,0 @@ -var inherits = require("util").inherits; - -// raised when the transaction is rejected prior to running it in the EVM. -function TXRejectedError(message) { - - // Why not just Error.apply(this, [message])? See - // https://gist.github.com/justmoon/15511f92e5216fa2624b#anti-patterns - Error.captureStackTrace(this, this.constructor) - this.name = this.constructor.name; - this.message = message; -}; - -inherits(TXRejectedError, Error); - -module.exports = TXRejectedError; diff --git a/lib/webSocketServer.js b/lib/webSocketServer.js deleted file mode 100644 index 17813eaa1b..0000000000 --- a/lib/webSocketServer.js +++ /dev/null @@ -1,130 +0,0 @@ -var WebSocketServer = require('websocket').server; -var to = require("./utils/to.js"); - -module.exports = function (httpServer, provider, logger) { - var connectionManager = new ConnectionManager(provider, logger); - - var wsServer = new WebSocketServer({ - httpServer: httpServer, - autoAcceptConnections: true, - }); - - wsServer.on('connect', connectionManager.manageConnection); - - return wsServer; -}; - - -function ConnectionManager(provider, logger) { - const self = this; - self.provider = provider; - self.logger = logger; - self.connectionsBySubscriptionId = {} - self.connections = {}; - self.connectionCounter = 0; - - self._updateSubscriptions = self._updateSubscriptions.bind(self) - self.manageConnection = self.manageConnection.bind(self); - self._logPayload = self._logPayload.bind(self); - self._handleRequest = self._handleRequest.bind(self); - - provider.on('data', function (err, notification) { - self._updateSubscriptions.call(self, notification); - }); -} - - -ConnectionManager.prototype.manageConnection = function (connection) { - const self = this; - connection.id = ++self.connectionCounter; - self.connections[ connection.id ] = { - connection: connection, - subscriptions: {} - }; - - connection.on('message', function (message) { - try { - var payload = JSON.parse(message.utf8Data); - } catch (e) { - connection.reject(400, 'Bad Request'); - } - - self._logPayload(payload); - self._handleRequest(connection, payload); - }); - - connection.on('close', function () { - console.log(`handling connection close: id ${connection.id}`) - // remove subscriptions - Object.keys(self.connections[connection.id].subscriptions).forEach((subscriptionId) => { - self.provider.send({ - jsonrpc: "2.0", - method: "eth_unsubscribe", - params: [subscriptionId], - id: new Date().getTime() - }, function(err, result) { - delete self.connectionsBySubscriptionId[subscriptionId]; - }); - }); - - delete self.connections[ connection.id ]; - }); - - console.log(`opened connection: id ${connection.id}`) -}; - - -ConnectionManager.prototype._handleRequest = function (connection, payload) { - const self = this; - - // handle subscription requests, otherwise delegate to provider - switch (payload.method) { - case 'eth_subscribe': - self.provider.send(payload, function (err, result) { - if (!err && result.result) { - self.connections[connection.id].subscriptions[result.result] = true; - self.connectionsBySubscriptionId[result.result] = self.connections[connection.id]; - } - connection.send(JSON.stringify(result)); - }); - break; - case 'eth_unsubscribe': - console.log(`handling unsubscribe: id ${connection.id}, ${payload.params[0]}`) - self.provider.send(payload, function (err, result) { - if (err || result.error) { - if (connection && connection.send) { - connection.send(JSON.stringify(result)) - } - return - } - - delete self.connections[connection.id].subscriptions[payload.params[0]] - delete self.connectionsBySubscriptionId[payload.params[0]]; - - connection.send(JSON.stringify(result)); - }); - break; - default: - self.provider.send(payload, function (err, result) { - connection.send(JSON.stringify(result)); - }); - } -}; - -// Log messages that come into the TestRPC via http -ConnectionManager.prototype._logPayload = function (payload) { - const self = this; - if (payload instanceof Array) { - // Batch request - for (var i = 0; i < payload.length; i++) { - var item = payload[ i ]; - self.logger.log(item.method); - } - } else { - self.logger.log(payload.method); - } -}; - -ConnectionManager.prototype._updateSubscriptions = function (notification) { - this.connectionsBySubscriptionId[notification.params.subscription].connection.send(JSON.stringify(notification)); -}; diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 73d33730a5..602cef2955 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,1051 +1,2773 @@ { - "name": "ganache-core", - "version": "2.2.1", - "lockfileVersion": 1, + "name": "root", "requires": true, + "lockfileVersion": 1, "dependencies": { - "@webassemblyjs/ast": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz", - "integrity": "sha512-49nwvW/Hx9i+OYHg+mRhKZfAlqThr11Dqz8TsrvqGKMhdI2ijy3KBJOun2Z4770TPjrIJhR6KxChQIDaz8clDA==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/wast-parser": "1.5.13", - "debug": "^3.1.0", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.5.13.tgz", - "integrity": "sha512-vrvvB18Kh4uyghSKb0NTv+2WZx871WL2NzwMj61jcq2bXkyhRC+8Q0oD7JGVf0+5i/fKQYQSBCNMMsDMRVAMqA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.5.13.tgz", - "integrity": "sha512-dBh2CWYqjaDlvMmRP/kudxpdh30uXjIbpkLj9HQe+qtYlwvYjPRjdQXrq1cTAAOUSMTtzqbXIxEdEZmyKfcwsg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.5.13.tgz", - "integrity": "sha512-v7igWf1mHcpJNbn4m7e77XOAWXCDT76Xe7Is1VQFXc4K5jRcFrl9D0NrqM4XifQ0bXiuTSkTKMYqDxu5MhNljA==", - "dev": true, - "requires": { - "debug": "^3.1.0" - } - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.5.13.tgz", - "integrity": "sha512-yN6ScQQDFCiAXnVctdVO/J5NQRbwyTbQzsGzEgXsAnrxhjp0xihh+nNHQTMrq5UhOqTb5LykpJAvEv9AT0jnAQ==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.5.13" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.5.13.tgz", - "integrity": "sha512-hSIKzbXjVMRvy3Jzhgu+vDd/aswJ+UMEnLRCkZDdknZO3Z9e6rp1DAs0tdLItjCFqkz9+0BeOPK/mk3eYvVzZg==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.5.13.tgz", - "integrity": "sha512-zxJXULGPLB7r+k+wIlvGlXpT4CYppRz8fLUM/xobGHc9Z3T6qlmJD9ySJ2jknuktuuiR9AjnNpKYDECyaiX+QQ==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "mamacro": "^0.0.3" + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/core": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", + "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.6", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.5", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.5", + "@babel/types": "^7.11.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } } }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.5.13.tgz", - "integrity": "sha512-0n3SoNGLvbJIZPhtMFq0XmmnA/YmQBXaZKQZcW8maGKwLpVcgjNrxpFZHEOLKjXJYVN5Il8vSfG7nRX50Zn+aw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.5.13.tgz", - "integrity": "sha512-IJ/goicOZ5TT1axZFSnlAtz4m8KEjYr12BNOANAwGFPKXM4byEDaMNXYowHMG0yKV9a397eU/NlibFaLwr1fbw==", + "@babel/generator": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "debug": "^3.1.0" + "@babel/types": "^7.11.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" } }, - "@webassemblyjs/ieee754": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.5.13.tgz", - "integrity": "sha512-TseswvXEPpG5TCBKoLx9tT7+/GMACjC1ruo09j46ULRZWYm8XHpDWaosOjTnI7kr4SRJFzA6MWoUkAB+YCGKKg==", + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", "dev": true, "requires": { - "ieee754": "^1.1.11" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, - "@webassemblyjs/leb128": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.5.13.tgz", - "integrity": "sha512-0NRMxrL+GG3eISGZBmLBLAVjphbN8Si15s7jzThaw1UE9e5BY1oH49/+MA1xBzxpf1OW5sf9OrPDOclk9wj2yg==", + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", "dev": true, "requires": { - "long": "4.0.0" - }, - "dependencies": { - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "dev": true - } + "@babel/types": "^7.10.4" } }, - "@webassemblyjs/utf8": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.5.13.tgz", - "integrity": "sha512-Ve1ilU2N48Ew0lVGB8FqY7V7hXjaC4+PeZM+vDYxEd+R2iQ0q+Wb3Rw8v0Ri0+rxhoz6gVGsnQNb4FjRiEH/Ng==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.5.13.tgz", - "integrity": "sha512-X7ZNW4+Hga4f2NmqENnHke2V/mGYK/xnybJSIXImt1ulxbCOEs/A+ZK/Km2jgihjyVxp/0z0hwIcxC6PrkWtgw==", + "@babel/helper-member-expression-to-functions": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/helper-wasm-section": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "@webassemblyjs/wasm-opt": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", - "@webassemblyjs/wast-printer": "1.5.13", - "debug": "^3.1.0" + "@babel/types": "^7.11.0" } }, - "@webassemblyjs/wasm-gen": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.5.13.tgz", - "integrity": "sha512-yfv94Se8R73zmr8GAYzezFHc3lDwE/lBXQddSiIZEKZFuqy7yWtm3KMwA1uGbv5G1WphimJxboXHR80IgX1hQA==", + "@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/ieee754": "1.5.13", - "@webassemblyjs/leb128": "1.5.13", - "@webassemblyjs/utf8": "1.5.13" + "@babel/types": "^7.10.4" } }, - "@webassemblyjs/wasm-opt": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.5.13.tgz", - "integrity": "sha512-IkXSkgzVhQ0QYAdIayuCWMmXSYx0dHGU8Ah/AxJf1gBvstMWVnzJnBwLsXLyD87VSBIcsqkmZ28dVb0mOC3oBg==", + "@babel/helper-module-transforms": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", - "debug": "^3.1.0" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" } }, - "@webassemblyjs/wasm-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.5.13.tgz", - "integrity": "sha512-XnYoIcu2iqq8/LrtmdnN3T+bRjqYFjRHqWbqK3osD/0r/Fcv4d9ecRzjVtC29ENEuNTK4mQ9yyxCBCbK8S/cpg==", + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-api-error": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/ieee754": "1.5.13", - "@webassemblyjs/leb128": "1.5.13", - "@webassemblyjs/utf8": "1.5.13" + "@babel/types": "^7.10.4" } }, - "@webassemblyjs/wast-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.5.13.tgz", - "integrity": "sha512-Lbz65T0LQ1LgzKiUytl34CwuhMNhaCLgrh0JW4rJBN6INnBB8NMwUfQM+FxTnLY9qJ+lHJL/gCM5xYhB9oWi4A==", + "@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/floating-point-hex-parser": "1.5.13", - "@webassemblyjs/helper-api-error": "1.5.13", - "@webassemblyjs/helper-code-frame": "1.5.13", - "@webassemblyjs/helper-fsm": "1.5.13", - "long": "^3.2.0", - "mamacro": "^0.0.3" + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, - "@webassemblyjs/wast-printer": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.5.13.tgz", - "integrity": "sha512-QcwogrdqcBh8Z+eUF8SG+ag5iwQSXxQJELBEHmLkk790wgQgnIMmntT2sMAMw53GiFNckArf5X0bsCA44j3lWQ==", + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/wast-parser": "1.5.13", - "long": "^3.2.0" - } - }, - "abstract-leveldown": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz", - "integrity": "sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ==", - "requires": { - "xtend": "~4.0.0" + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", "dev": true, "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" + "@babel/types": "^7.11.0" } }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", "dev": true, "requires": { - "acorn": "^5.0.0" + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, - "aes-js": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.1.tgz", - "integrity": "sha512-cEA0gBelItZZV7iBiL8ApCiNgc+gBWJJ4uoORhbu6vOqAJ0UL9wIlxr4RI7ij9SSVzy6AnPwiu37kVYiHCl3nw==", + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, - "optional": true - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" } }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "@babel/traverse": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", "dev": true, "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } } }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { - "util": "0.10.3" + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" } }, - "assert-match": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/assert-match/-/assert-match-1.1.1.tgz", - "integrity": "sha512-c0QY2kpYVrH/jis6cCq9Mnt4/bIdGALDh1N8HY9ZARZedsMs5LSbgywxkjd5A1uNVLN0L8evANxBPxKiabVoZw==", + "@evocateur/libnpmaccess": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz", + "integrity": "sha512-KSCAHwNWro0CF2ukxufCitT9K5LjL/KuMmNzSu8wuwN2rjyKHD8+cmOsiybK+W5hdnwc5M1SmRlVCaMHQo+3rg==", "dev": true, "requires": { - "assert": "^1.4.1", - "babel-runtime": "^6.23.0", - "es-to-primitive": "^1.1.1", - "lodash.merge": "^4.6.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "requires": { - "lodash": "^4.17.10" - } - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "async-eventemitter": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", - "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", - "requires": { - "async": "^2.4.0" - } - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" + "@evocateur/npm-registry-fetch": "^4.0.0", + "aproba": "^2.0.0", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.0.0", + "npm-package-arg": "^6.1.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, "requires": { - "ms": "2.0.0" + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" + "@evocateur/libnpmpublish": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@evocateur/libnpmpublish/-/libnpmpublish-1.2.2.tgz", + "integrity": "sha512-MJrrk9ct1FeY9zRlyeoyMieBjGDG9ihyyD9/Ft6MMrTxql9NyoEx2hw9casTIP4CdqEVu+3nQ2nXxoJ8RCXyFg==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "aproba": "^2.0.0", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.0.0", + "lodash.clonedeep": "^4.5.0", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "semver": "^5.5.1", + "ssri": "^6.0.1" }, "dependencies": { - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "@evocateur/npm-registry-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@evocateur/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz", + "integrity": "sha512-k1WGfKRQyhJpIr+P17O5vLIo2ko1PFLKwoetatdduUSt/aQ4J2sJrJwwatdI5Z3SiYk/mRH9S3JpdmMFd/IK4g==", + "dev": true, "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "JSONStream": "^1.3.4", + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "@evocateur/pacote": { + "version": "9.6.5", + "resolved": "https://registry.npmjs.org/@evocateur/pacote/-/pacote-9.6.5.tgz", + "integrity": "sha512-EI552lf0aG2nOV8NnZpTxNo2PcXKPmDbF9K8eCBFQdIZwHNGN/mi815fxtmUMa2wTa1yndotICIDt/V0vpEx2w==", + "dev": true, "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "@evocateur/npm-registry-fetch": "^4.0.0", + "bluebird": "^3.5.3", + "cacache": "^12.0.3", + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.5.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.4.4", + "npm-pick-manifest": "^3.0.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.3", + "safe-buffer": "^5.2.0", + "semver": "^5.7.0", + "ssri": "^6.0.1", + "tar": "^4.4.10", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/nyc-config-typescript": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.1.tgz", + "integrity": "sha512-/gz6LgVpky205LuoOfwEZmnUtaSmdk0QIMcNFj9OvxhiMhPpKftMgZmGN7jNj7jR+lr8IB1Yks3QSSSNSxfoaQ==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2" + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@lerna/add": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/add/-/add-3.21.0.tgz", + "integrity": "sha512-vhUXXF6SpufBE1EkNEXwz1VLW03f177G9uMOFMQkp6OJ30/PWg4Ekifuz9/3YfgB2/GH8Tu4Lk3O51P2Hskg/A==", + "dev": true, + "requires": { + "@evocateur/pacote": "^9.6.3", + "@lerna/bootstrap": "3.21.0", + "@lerna/command": "3.21.0", + "@lerna/filter-options": "3.20.0", + "@lerna/npm-conf": "3.16.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "npm-package-arg": "^6.1.0", + "p-map": "^2.1.0", + "semver": "^6.2.0" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/bootstrap": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-3.21.0.tgz", + "integrity": "sha512-mtNHlXpmvJn6JTu0KcuTTPl2jLsDNud0QacV/h++qsaKbhAaJr/FElNZ5s7MwZFUM3XaDmvWzHKaszeBMHIbBw==", + "dev": true, + "requires": { + "@lerna/command": "3.21.0", + "@lerna/filter-options": "3.20.0", + "@lerna/has-npm-version": "3.16.5", + "@lerna/npm-install": "3.16.5", + "@lerna/package-graph": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/rimraf-dir": "3.16.5", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/symlink-binary": "3.17.0", + "@lerna/symlink-dependencies": "3.17.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "get-port": "^4.2.0", + "multimatch": "^3.0.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0", + "p-waterfall": "^1.0.0", + "read-package-tree": "^5.1.6", + "semver": "^6.2.0" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/changed": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/changed/-/changed-3.21.0.tgz", + "integrity": "sha512-hzqoyf8MSHVjZp0gfJ7G8jaz+++mgXYiNs9iViQGA8JlN/dnWLI5sWDptEH3/B30Izo+fdVz0S0s7ydVE3pWIw==", + "dev": true, + "requires": { + "@lerna/collect-updates": "3.20.0", + "@lerna/command": "3.21.0", + "@lerna/listable": "3.18.5", + "@lerna/output": "3.13.0" + } + }, + "@lerna/check-working-tree": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-3.16.5.tgz", + "integrity": "sha512-xWjVBcuhvB8+UmCSb5tKVLB5OuzSpw96WEhS2uz6hkWVa/Euh1A0/HJwn2cemyK47wUrCQXtczBUiqnq9yX5VQ==", + "dev": true, + "requires": { + "@lerna/collect-uncommitted": "3.16.5", + "@lerna/describe-ref": "3.16.5", + "@lerna/validation-error": "3.13.0" + } + }, + "@lerna/child-process": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-3.16.5.tgz", + "integrity": "sha512-vdcI7mzei9ERRV4oO8Y1LHBZ3A5+ampRKg1wq5nutLsUA4mEBN6H7JqjWOMY9xZemv6+kATm2ofjJ3lW5TszQg==", + "dev": true, + "requires": { + "chalk": "^2.3.1", + "execa": "^1.0.0", + "strong-log-transformer": "^2.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@lerna/clean": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/clean/-/clean-3.21.0.tgz", + "integrity": "sha512-b/L9l+MDgE/7oGbrav6rG8RTQvRiZLO1zTcG17zgJAAuhlsPxJExMlh2DFwJEVi2les70vMhHfST3Ue1IMMjpg==", + "dev": true, + "requires": { + "@lerna/command": "3.21.0", + "@lerna/filter-options": "3.20.0", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/rimraf-dir": "3.16.5", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0", + "p-waterfall": "^1.0.0" + } + }, + "@lerna/cli": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/cli/-/cli-3.18.5.tgz", + "integrity": "sha512-erkbxkj9jfc89vVs/jBLY/fM0I80oLmJkFUV3Q3wk9J3miYhP14zgVEBsPZY68IZlEjT6T3Xlq2xO1AVaatHsA==", + "dev": true, + "requires": { + "@lerna/global-options": "3.13.0", + "dedent": "^0.7.0", + "npmlog": "^4.1.2", + "yargs": "^14.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + } + } + }, + "@lerna/collect-uncommitted": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-3.16.5.tgz", + "integrity": "sha512-ZgqnGwpDZiWyzIQVZtQaj9tRizsL4dUOhuOStWgTAw1EMe47cvAY2kL709DzxFhjr6JpJSjXV5rZEAeU3VE0Hg==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "chalk": "^2.3.1", + "figgy-pudding": "^3.5.1", + "npmlog": "^4.1.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@lerna/collect-updates": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-3.20.0.tgz", + "integrity": "sha512-qBTVT5g4fupVhBFuY4nI/3FSJtQVcDh7/gEPOpRxoXB/yCSnT38MFHXWl+y4einLciCjt/+0x6/4AG80fjay2Q==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/describe-ref": "3.16.5", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "slash": "^2.0.0" + } + }, + "@lerna/command": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/command/-/command-3.21.0.tgz", + "integrity": "sha512-T2bu6R8R3KkH5YoCKdutKv123iUgUbW8efVjdGCDnCMthAQzoentOJfDeodBwn0P2OqCl3ohsiNVtSn9h78fyQ==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/package-graph": "3.18.5", + "@lerna/project": "3.21.0", + "@lerna/validation-error": "3.13.0", + "@lerna/write-log-file": "3.13.0", + "clone-deep": "^4.0.1", + "dedent": "^0.7.0", + "execa": "^1.0.0", + "is-ci": "^2.0.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/conventional-commits": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-3.22.0.tgz", + "integrity": "sha512-z4ZZk1e8Mhz7+IS8NxHr64wyklHctCJyWpJKEZZPJiLFJ8yKto/x38O80R10pIzC0rr8Sy/OsjSH4bl0TbbgqA==", + "dev": true, + "requires": { + "@lerna/validation-error": "3.13.0", + "conventional-changelog-angular": "^5.0.3", + "conventional-changelog-core": "^3.1.6", + "conventional-recommended-bump": "^5.0.0", + "fs-extra": "^8.1.0", + "get-stream": "^4.0.0", + "lodash.template": "^4.5.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "pify": "^4.0.1", + "semver": "^6.2.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/create": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/@lerna/create/-/create-3.22.0.tgz", + "integrity": "sha512-MdiQQzCcB4E9fBF1TyMOaAEz9lUjIHp1Ju9H7f3lXze5JK6Fl5NYkouAvsLgY6YSIhXMY8AHW2zzXeBDY4yWkw==", + "dev": true, + "requires": { + "@evocateur/pacote": "^9.6.3", + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.21.0", + "@lerna/npm-conf": "3.16.0", + "@lerna/validation-error": "3.13.0", + "camelcase": "^5.0.0", + "dedent": "^0.7.0", + "fs-extra": "^8.1.0", + "globby": "^9.2.0", + "init-package-json": "^1.10.3", + "npm-package-arg": "^6.1.0", + "p-reduce": "^1.0.0", + "pify": "^4.0.1", + "semver": "^6.2.0", + "slash": "^2.0.0", + "validate-npm-package-license": "^3.0.3", + "validate-npm-package-name": "^3.0.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/create-symlink": { + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-3.16.2.tgz", + "integrity": "sha512-pzXIJp6av15P325sgiIRpsPXLFmkisLhMBCy4764d+7yjf2bzrJ4gkWVMhsv4AdF0NN3OyZ5jjzzTtLNqfR+Jw==", + "dev": true, + "requires": { + "@zkochan/cmd-shim": "^3.1.0", + "fs-extra": "^8.1.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/describe-ref": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-3.16.5.tgz", + "integrity": "sha512-c01+4gUF0saOOtDBzbLMFOTJDHTKbDFNErEY6q6i9QaXuzy9LNN62z+Hw4acAAZuJQhrVWncVathcmkkjvSVGw==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "npmlog": "^4.1.2" + } + }, + "@lerna/diff": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/diff/-/diff-3.21.0.tgz", + "integrity": "sha512-5viTR33QV3S7O+bjruo1SaR40m7F2aUHJaDAC7fL9Ca6xji+aw1KFkpCtVlISS0G8vikUREGMJh+c/VMSc8Usw==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.21.0", + "@lerna/validation-error": "3.13.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/exec": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/exec/-/exec-3.21.0.tgz", + "integrity": "sha512-iLvDBrIE6rpdd4GIKTY9mkXyhwsJ2RvQdB9ZU+/NhR3okXfqKc6py/24tV111jqpXTtZUW6HNydT4dMao2hi1Q==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.21.0", + "@lerna/filter-options": "3.20.0", + "@lerna/profiler": "3.20.0", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "p-map": "^2.1.0" + } + }, + "@lerna/filter-options": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-3.20.0.tgz", + "integrity": "sha512-bmcHtvxn7SIl/R9gpiNMVG7yjx7WyT0HSGw34YVZ9B+3xF/83N3r5Rgtjh4hheLZ+Q91Or0Jyu5O3Nr+AwZe2g==", + "dev": true, + "requires": { + "@lerna/collect-updates": "3.20.0", + "@lerna/filter-packages": "3.18.0", + "dedent": "^0.7.0", + "figgy-pudding": "^3.5.1", + "npmlog": "^4.1.2" + } + }, + "@lerna/filter-packages": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-3.18.0.tgz", + "integrity": "sha512-6/0pMM04bCHNATIOkouuYmPg6KH3VkPCIgTfQmdkPJTullERyEQfNUKikrefjxo1vHOoCACDpy65JYyKiAbdwQ==", + "dev": true, + "requires": { + "@lerna/validation-error": "3.13.0", + "multimatch": "^3.0.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/get-npm-exec-opts": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz", + "integrity": "sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw==", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/get-packed": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-3.16.0.tgz", + "integrity": "sha512-AjsFiaJzo1GCPnJUJZiTW6J1EihrPkc2y3nMu6m3uWFxoleklsSCyImumzVZJssxMi3CPpztj8LmADLedl9kXw==", + "dev": true, + "requires": { + "fs-extra": "^8.1.0", + "ssri": "^6.0.1", + "tar": "^4.4.8" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/github-client": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/@lerna/github-client/-/github-client-3.22.0.tgz", + "integrity": "sha512-O/GwPW+Gzr3Eb5bk+nTzTJ3uv+jh5jGho9BOqKlajXaOkMYGBELEAqV5+uARNGWZFvYAiF4PgqHb6aCUu7XdXg==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@octokit/plugin-enterprise-rest": "^6.0.1", + "@octokit/rest": "^16.28.4", + "git-url-parse": "^11.1.2", + "npmlog": "^4.1.2" + } + }, + "@lerna/gitlab-client": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz", + "integrity": "sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q==", + "dev": true, + "requires": { + "node-fetch": "^2.5.0", + "npmlog": "^4.1.2", + "whatwg-url": "^7.0.0" + } + }, + "@lerna/global-options": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-3.13.0.tgz", + "integrity": "sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ==", + "dev": true + }, + "@lerna/has-npm-version": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-3.16.5.tgz", + "integrity": "sha512-WL7LycR9bkftyqbYop5rEGJ9sRFIV55tSGmbN1HLrF9idwOCD7CLrT64t235t3t4O5gehDnwKI5h2U3oxTrF8Q==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/import": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/@lerna/import/-/import-3.22.0.tgz", + "integrity": "sha512-uWOlexasM5XR6tXi4YehODtH9Y3OZrFht3mGUFFT3OIl2s+V85xIGFfqFGMTipMPAGb2oF1UBLL48kR43hRsOg==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.21.0", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "fs-extra": "^8.1.0", + "p-map-series": "^1.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/info": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/info/-/info-3.21.0.tgz", + "integrity": "sha512-0XDqGYVBgWxUquFaIptW2bYSIu6jOs1BtkvRTWDDhw4zyEdp6q4eaMvqdSap1CG+7wM5jeLCi6z94wS0AuiuwA==", + "dev": true, + "requires": { + "@lerna/command": "3.21.0", + "@lerna/output": "3.13.0", + "envinfo": "^7.3.1" + } + }, + "@lerna/init": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/init/-/init-3.21.0.tgz", + "integrity": "sha512-6CM0z+EFUkFfurwdJCR+LQQF6MqHbYDCBPyhu/d086LRf58GtYZYj49J8mKG9ktayp/TOIxL/pKKjgLD8QBPOg==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.21.0", + "fs-extra": "^8.1.0", + "p-map": "^2.1.0", + "write-json-file": "^3.2.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/link": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/link/-/link-3.21.0.tgz", + "integrity": "sha512-tGu9GxrX7Ivs+Wl3w1+jrLi1nQ36kNI32dcOssij6bg0oZ2M2MDEFI9UF2gmoypTaN9uO5TSsjCFS7aR79HbdQ==", + "dev": true, + "requires": { + "@lerna/command": "3.21.0", + "@lerna/package-graph": "3.18.5", + "@lerna/symlink-dependencies": "3.17.0", + "p-map": "^2.1.0", + "slash": "^2.0.0" + } + }, + "@lerna/list": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/list/-/list-3.21.0.tgz", + "integrity": "sha512-KehRjE83B1VaAbRRkRy6jLX1Cin8ltsrQ7FHf2bhwhRHK0S54YuA6LOoBnY/NtA8bHDX/Z+G5sMY78X30NS9tg==", + "dev": true, + "requires": { + "@lerna/command": "3.21.0", + "@lerna/filter-options": "3.20.0", + "@lerna/listable": "3.18.5", + "@lerna/output": "3.13.0" + } + }, + "@lerna/listable": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-3.18.5.tgz", + "integrity": "sha512-Sdr3pVyaEv5A7ZkGGYR7zN+tTl2iDcinryBPvtuv20VJrXBE8wYcOks1edBTcOWsPjCE/rMP4bo1pseyk3UTsg==", + "dev": true, + "requires": { + "@lerna/query-graph": "3.18.5", + "chalk": "^2.3.1", + "columnify": "^1.5.4" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@lerna/log-packed": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-3.16.0.tgz", + "integrity": "sha512-Fp+McSNBV/P2mnLUYTaSlG8GSmpXM7krKWcllqElGxvAqv6chk2K3c2k80MeVB4WvJ9tRjUUf+i7HUTiQ9/ckQ==", + "dev": true, + "requires": { + "byte-size": "^5.0.1", + "columnify": "^1.5.4", + "has-unicode": "^2.0.1", + "npmlog": "^4.1.2" + } + }, + "@lerna/npm-conf": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-3.16.0.tgz", + "integrity": "sha512-HbO3DUrTkCAn2iQ9+FF/eisDpWY5POQAOF1m7q//CZjdC2HSW3UYbKEGsSisFxSfaF9Z4jtrV+F/wX6qWs3CuA==", + "dev": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^4.0.1" + } + }, + "@lerna/npm-dist-tag": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-3.18.5.tgz", + "integrity": "sha512-xw0HDoIG6HreVsJND9/dGls1c+lf6vhu7yJoo56Sz5bvncTloYGLUppIfDHQr4ZvmPCK8rsh0euCVh2giPxzKQ==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "@lerna/otplease": "3.18.5", + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@lerna/npm-install": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-3.16.5.tgz", + "integrity": "sha512-hfiKk8Eku6rB9uApqsalHHTHY+mOrrHeWEs+gtg7+meQZMTS3kzv4oVp5cBZigndQr3knTLjwthT/FX4KvseFg==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/get-npm-exec-opts": "3.13.0", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "signal-exit": "^3.0.2", + "write-pkg": "^3.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/npm-publish": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-3.18.5.tgz", + "integrity": "sha512-3etLT9+2L8JAx5F8uf7qp6iAtOLSMj+ZYWY6oUgozPi/uLqU0/gsMsEXh3F0+YVW33q0M61RpduBoAlOOZnaTg==", + "dev": true, + "requires": { + "@evocateur/libnpmpublish": "^1.2.2", + "@lerna/otplease": "3.18.5", + "@lerna/run-lifecycle": "3.16.2", + "figgy-pudding": "^3.5.1", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "pify": "^4.0.1", + "read-package-json": "^2.0.13" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/npm-run-script": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-3.16.5.tgz", + "integrity": "sha512-1asRi+LjmVn3pMjEdpqKJZFT/3ZNpb+VVeJMwrJaV/3DivdNg7XlPK9LTrORuKU4PSvhdEZvJmSlxCKyDpiXsQ==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/get-npm-exec-opts": "3.13.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/otplease": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-3.18.5.tgz", + "integrity": "sha512-S+SldXAbcXTEDhzdxYLU0ZBKuYyURP/ND2/dK6IpKgLxQYh/z4ScljPDMyKymmEvgiEJmBsPZAAPfmNPEzxjog==", + "dev": true, + "requires": { + "@lerna/prompt": "3.18.5", + "figgy-pudding": "^3.5.1" + } + }, + "@lerna/output": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/output/-/output-3.13.0.tgz", + "integrity": "sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg==", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/pack-directory": { + "version": "3.16.4", + "resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-3.16.4.tgz", + "integrity": "sha512-uxSF0HZeGyKaaVHz5FroDY9A5NDDiCibrbYR6+khmrhZtY0Bgn6hWq8Gswl9iIlymA+VzCbshWIMX4o2O8C8ng==", + "dev": true, + "requires": { + "@lerna/get-packed": "3.16.0", + "@lerna/package": "3.16.0", + "@lerna/run-lifecycle": "3.16.2", + "figgy-pudding": "^3.5.1", + "npm-packlist": "^1.4.4", + "npmlog": "^4.1.2", + "tar": "^4.4.10", + "temp-write": "^3.4.0" + } + }, + "@lerna/package": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/package/-/package-3.16.0.tgz", + "integrity": "sha512-2lHBWpaxcBoiNVbtyLtPUuTYEaB/Z+eEqRS9duxpZs6D+mTTZMNy6/5vpEVSCBmzvdYpyqhqaYjjSLvjjr5Riw==", + "dev": true, + "requires": { + "load-json-file": "^5.3.0", + "npm-package-arg": "^6.1.0", + "write-pkg": "^3.1.0" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@lerna/package-graph": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-3.18.5.tgz", + "integrity": "sha512-8QDrR9T+dBegjeLr+n9WZTVxUYUhIUjUgZ0gvNxUBN8S1WB9r6H5Yk56/MVaB64tA3oGAN9IIxX6w0WvTfFudA==", + "dev": true, + "requires": { + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/validation-error": "3.13.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "semver": "^6.2.0" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/prerelease-id-from-version": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.16.0.tgz", + "integrity": "sha512-qZyeUyrE59uOK8rKdGn7jQz+9uOpAaF/3hbslJVFL1NqF9ELDTqjCPXivuejMX/lN4OgD6BugTO4cR7UTq/sZA==", + "dev": true, + "requires": { + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/profiler": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@lerna/profiler/-/profiler-3.20.0.tgz", + "integrity": "sha512-bh8hKxAlm6yu8WEOvbLENm42i2v9SsR4WbrCWSbsmOElx3foRnMlYk7NkGECa+U5c3K4C6GeBbwgqs54PP7Ljg==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "fs-extra": "^8.1.0", + "npmlog": "^4.1.2", + "upath": "^1.2.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/project": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/project/-/project-3.21.0.tgz", + "integrity": "sha512-xT1mrpET2BF11CY32uypV2GPtPVm6Hgtha7D81GQP9iAitk9EccrdNjYGt5UBYASl4CIDXBRxwmTTVGfrCx82A==", + "dev": true, + "requires": { + "@lerna/package": "3.16.0", + "@lerna/validation-error": "3.13.0", + "cosmiconfig": "^5.1.0", + "dedent": "^0.7.0", + "dot-prop": "^4.2.0", + "glob-parent": "^5.0.0", + "globby": "^9.2.0", + "load-json-file": "^5.3.0", + "npmlog": "^4.1.2", + "p-map": "^2.1.0", + "resolve-from": "^4.0.0", + "write-json-file": "^3.2.0" + } + }, + "@lerna/prompt": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-3.18.5.tgz", + "integrity": "sha512-rkKj4nm1twSbBEb69+Em/2jAERK8htUuV8/xSjN0NPC+6UjzAwY52/x9n5cfmpa9lyKf/uItp7chCI7eDmNTKQ==", + "dev": true, + "requires": { + "inquirer": "^6.2.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/publish": { + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-3.22.1.tgz", + "integrity": "sha512-PG9CM9HUYDreb1FbJwFg90TCBQooGjj+n/pb3gw/eH5mEDq0p8wKdLFe0qkiqUkm/Ub5C8DbVFertIo0Vd0zcw==", + "dev": true, + "requires": { + "@evocateur/libnpmaccess": "^3.1.2", + "@evocateur/npm-registry-fetch": "^4.0.0", + "@evocateur/pacote": "^9.6.3", + "@lerna/check-working-tree": "3.16.5", + "@lerna/child-process": "3.16.5", + "@lerna/collect-updates": "3.20.0", + "@lerna/command": "3.21.0", + "@lerna/describe-ref": "3.16.5", + "@lerna/log-packed": "3.16.0", + "@lerna/npm-conf": "3.16.0", + "@lerna/npm-dist-tag": "3.18.5", + "@lerna/npm-publish": "3.18.5", + "@lerna/otplease": "3.18.5", + "@lerna/output": "3.13.0", + "@lerna/pack-directory": "3.16.4", + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "@lerna/version": "3.22.1", + "figgy-pudding": "^3.5.1", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-pipe": "^1.2.0", + "semver": "^6.2.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/pulse-till-done": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz", + "integrity": "sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA==", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/query-graph": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-3.18.5.tgz", + "integrity": "sha512-50Lf4uuMpMWvJ306be3oQDHrWV42nai9gbIVByPBYJuVW8dT8O8pA3EzitNYBUdLL9/qEVbrR0ry1HD7EXwtRA==", + "dev": true, + "requires": { + "@lerna/package-graph": "3.18.5", + "figgy-pudding": "^3.5.1" + } + }, + "@lerna/resolve-symlink": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-3.16.0.tgz", + "integrity": "sha512-Ibj5e7njVHNJ/NOqT4HlEgPFPtPLWsO7iu59AM5bJDcAJcR96mLZ7KGVIsS2tvaO7akMEJvt2P+ErwCdloG3jQ==", + "dev": true, + "requires": { + "fs-extra": "^8.1.0", + "npmlog": "^4.1.2", + "read-cmd-shim": "^1.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/rimraf-dir": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-3.16.5.tgz", + "integrity": "sha512-bQlKmO0pXUsXoF8lOLknhyQjOZsCc0bosQDoX4lujBXSWxHVTg1VxURtWf2lUjz/ACsJVDfvHZbDm8kyBk5okA==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "npmlog": "^4.1.2", + "path-exists": "^3.0.0", + "rimraf": "^2.6.2" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "@lerna/run": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@lerna/run/-/run-3.21.0.tgz", + "integrity": "sha512-fJF68rT3veh+hkToFsBmUJ9MHc9yGXA7LSDvhziAojzOb0AI/jBDp6cEcDQyJ7dbnplba2Lj02IH61QUf9oW0Q==", + "dev": true, + "requires": { + "@lerna/command": "3.21.0", + "@lerna/filter-options": "3.20.0", + "@lerna/npm-run-script": "3.16.5", + "@lerna/output": "3.13.0", + "@lerna/profiler": "3.20.0", + "@lerna/run-topologically": "3.18.5", + "@lerna/timer": "3.13.0", + "@lerna/validation-error": "3.13.0", + "p-map": "^2.1.0" + } + }, + "@lerna/run-lifecycle": { + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-3.16.2.tgz", + "integrity": "sha512-RqFoznE8rDpyyF0rOJy3+KjZCeTkO8y/OB9orPauR7G2xQ7PTdCpgo7EO6ZNdz3Al+k1BydClZz/j78gNCmL2A==", + "dev": true, + "requires": { + "@lerna/npm-conf": "3.16.0", + "figgy-pudding": "^3.5.1", + "npm-lifecycle": "^3.1.2", + "npmlog": "^4.1.2" + } + }, + "@lerna/run-topologically": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-3.18.5.tgz", + "integrity": "sha512-6N1I+6wf4hLOnPW+XDZqwufyIQ6gqoPfHZFkfWlvTQ+Ue7CuF8qIVQ1Eddw5HKQMkxqN10thKOFfq/9NQZ4NUg==", + "dev": true, + "requires": { + "@lerna/query-graph": "3.18.5", + "figgy-pudding": "^3.5.1", + "p-queue": "^4.0.0" + } + }, + "@lerna/symlink-binary": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-3.17.0.tgz", + "integrity": "sha512-RLpy9UY6+3nT5J+5jkM5MZyMmjNHxZIZvXLV+Q3MXrf7Eaa1hNqyynyj4RO95fxbS+EZc4XVSk25DGFQbcRNSQ==", + "dev": true, + "requires": { + "@lerna/create-symlink": "3.16.2", + "@lerna/package": "3.16.0", + "fs-extra": "^8.1.0", + "p-map": "^2.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@lerna/symlink-dependencies": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-3.17.0.tgz", + "integrity": "sha512-KmjU5YT1bpt6coOmdFueTJ7DFJL4H1w5eF8yAQ2zsGNTtZ+i5SGFBWpb9AQaw168dydc3s4eu0W0Sirda+F59Q==", + "dev": true, + "requires": { + "@lerna/create-symlink": "3.16.2", + "@lerna/resolve-symlink": "3.16.0", + "@lerna/symlink-binary": "3.17.0", + "fs-extra": "^8.1.0", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } } }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "@lerna/timer": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-3.13.0.tgz", + "integrity": "sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw==", + "dev": true + }, + "@lerna/validation-error": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-3.13.0.tgz", + "integrity": "sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA==", + "dev": true, "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "npmlog": "^4.1.2" } }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "@lerna/version": { + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/@lerna/version/-/version-3.22.1.tgz", + "integrity": "sha512-PSGt/K1hVqreAFoi3zjD0VEDupQ2WZVlVIwesrE5GbrL2BjXowjCsTDPqblahDUPy0hp6h7E2kG855yLTp62+g==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "@lerna/check-working-tree": "3.16.5", + "@lerna/child-process": "3.16.5", + "@lerna/collect-updates": "3.20.0", + "@lerna/command": "3.21.0", + "@lerna/conventional-commits": "3.22.0", + "@lerna/github-client": "3.22.0", + "@lerna/gitlab-client": "3.15.0", + "@lerna/output": "3.13.0", + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/prompt": "3.18.5", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "chalk": "^2.3.1", + "dedent": "^0.7.0", + "load-json-file": "^5.3.0", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "p-map": "^2.1.0", + "p-pipe": "^1.2.0", + "p-reduce": "^1.0.0", + "p-waterfall": "^1.0.0", + "semver": "^6.2.0", + "slash": "^2.0.0", + "temp-write": "^3.4.0", + "write-json-file": "^3.2.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "@lerna/write-log-file": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-3.13.0.tgz", + "integrity": "sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "npmlog": "^4.1.2", + "write-file-atomic": "^2.3.0" } }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" } }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "@octokit/auth-token": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.2.tgz", + "integrity": "sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ==", + "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "@octokit/types": "^5.0.0" } }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "@octokit/endpoint": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.6.tgz", + "integrity": "sha512-7Cc8olaCoL/mtquB7j/HTbPM+sY6Ebr4k2X2y4JoXpVKQ7r5xB4iGQE0IoO58wIPsUk4AzoT65AMEpymSbWTgQ==", + "dev": true, "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "@octokit/types": "^5.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + } } }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "@octokit/plugin-enterprise-rest": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", + "integrity": "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==", + "dev": true + }, + "@octokit/plugin-paginate-rest": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz", + "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==", + "dev": true, "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "@octokit/types": "^2.0.1" + }, + "dependencies": { + "@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } + } } }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "@octokit/plugin-request-log": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz", + "integrity": "sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==", + "dev": true + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz", + "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "@octokit/types": "^2.0.1", + "deprecation": "^2.3.1" + }, + "dependencies": { + "@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } + } } }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "@octokit/request": { + "version": "5.4.9", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.9.tgz", + "integrity": "sha512-CzwVvRyimIM1h2n9pLVYfTDmX9m+KHSgCpqPsY8F1NdEK8IaWqXhSBXsdjOBFZSpEcxNEeg4p0UO9cQ8EnOCLA==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.0.0", + "@octokit/types": "^5.0.0", + "deprecation": "^2.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "once": "^1.4.0", + "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "@octokit/request-error": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.2.tgz", + "integrity": "sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw==", + "dev": true, + "requires": { + "@octokit/types": "^5.0.1", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + } } }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "@octokit/request-error": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", + "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "@octokit/types": "^2.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "dependencies": { + "@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } + } } }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" + "@octokit/rest": { + "version": "16.43.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz", + "integrity": "sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==", + "dev": true, + "requires": { + "@octokit/auth-token": "^2.4.0", + "@octokit/plugin-paginate-rest": "^1.1.1", + "@octokit/plugin-request-log": "^1.0.0", + "@octokit/plugin-rest-endpoint-methods": "2.4.0", + "@octokit/request": "^5.2.0", + "@octokit/request-error": "^1.0.2", + "atob-lite": "^2.0.0", + "before-after-hook": "^2.0.0", + "btoa-lite": "^1.0.0", + "deprecation": "^2.0.0", + "lodash.get": "^4.4.2", + "lodash.set": "^4.3.2", + "lodash.uniq": "^4.5.0", + "octokit-pagination-methods": "^1.1.0", + "once": "^1.4.0", + "universal-user-agent": "^4.0.0" + } }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" + "@octokit/types": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz", + "integrity": "sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" + "@types/fs-extra": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.2.tgz", + "integrity": "sha512-jp0RI6xfZpi5JL8v7WQwpBEQTq63RqW2kxwTZt+m27LcJqQdPVU1yGnT1ZI4EtCDynQQJtIGyQahkiCGCS7e+A==", + "dev": true, + "requires": { + "@types/node": "*" + } }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" + "@types/minimatch": "*", + "@types/node": "*" } }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "dev": true + }, + "@types/mocha": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.3.tgz", + "integrity": "sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg==", + "dev": true + }, + "@types/node": { + "version": "14.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz", + "integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "dev": true + }, + "@types/npm-package-arg": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.0.tgz", + "integrity": "sha512-vbt5fb0y1svMhu++1lwtKmZL76d0uPChFlw7kEzyUmTwfmpHRcFb8i0R8ElT69q/L+QLgK2hgECivIAvaEDwag==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/prettier": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz", + "integrity": "sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ==", + "dev": true + }, + "@types/yargs": { + "version": "15.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.9.tgz", + "integrity": "sha512-HmU8SeIRhZCWcnRskCs36Q1Q00KBV6Cqh/ora8WN1+22dY07AZdn6Gel8QZ3t26XYPImtcL8WV/eqjhVmMEw4g==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "@types/yargs-parser": "*" } }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "@types/yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "dev": true + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "@zerollup/ts-helpers": { + "version": "1.7.18", + "resolved": "https://registry.npmjs.org/@zerollup/ts-helpers/-/ts-helpers-1.7.18.tgz", + "integrity": "sha512-S9zN+y+i5yN/evfWquzSO3lubqPXIsPQf6p9OiPMpRxDx/0totPLF39XoRw48Dav5dSvbIE8D2eAPpXXJxvKwg==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "resolve": "^1.12.0" } }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "@zerollup/ts-transform-paths": { + "version": "1.7.18", + "resolved": "https://registry.npmjs.org/@zerollup/ts-transform-paths/-/ts-transform-paths-1.7.18.tgz", + "integrity": "sha512-YPVUxvWQVzRx1OBN0Pmkd58+R9FcfUJuwTaPUSoi5rKxuXMtxevTXdfi0w5mEaIH8b0DfL+wg0wFDHiJE+S2zA==", + "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "@zerollup/ts-helpers": "^1.7.18" } }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "@zkochan/cmd-shim": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz", + "integrity": "sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg==", + "dev": true, "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "is-windows": "^1.0.0", + "mkdirp-promise": "^5.0.1", + "mz": "^2.5.0" } }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" } }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "es6-promisify": "^5.0.0" } }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "humanize-ms": "^1.2.1" } }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" } }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "dev": true, "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "color-convert": "^1.9.0" } }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" + "default-require-extensions": "^3.0.0" } }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" + "sprintf-js": "~1.0.2" } }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "requires": { - "babel-runtime": "^6.22.0" - } + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "array-differ": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz", + "integrity": "sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==", + "dev": true }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "requires": { - "babel-runtime": "^6.22.0" - } + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "requires": { - "babel-runtime": "^6.22.0" - } + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" + "array-uniq": "^1.0.1" } }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "requires": { - "regenerator-transform": "^0.10.0" - } + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true }, - "babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - }, - "dependencies": { - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "requires": { - "source-map": "^0.5.6" - } - } - } + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "safer-buffer": "~2.1.0" } }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true }, - "babelify": { - "version": "7.3.0", - "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", - "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", - "requires": { - "babel-core": "^6.0.14", - "object-assign": "^4.0.0" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - } - } + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + "atob-lite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", + "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", + "dev": true }, - "backoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", - "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", - "requires": { - "precond": "0.2" - } + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", + "dev": true }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", @@ -1102,131 +2824,38 @@ } } }, - "base-x": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", - "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, "requires": { "tweetnacl": "^0.14.3" } }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "before-after-hook": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", + "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==", "dev": true }, "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, - "bindings": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", - "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" - }, - "bip39": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", - "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", - "requires": { - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1", - "safe-buffer": "^5.0.1", - "unorm": "^1.3.3" - } - }, - "bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "bl": { - "version": "1.2.2", - "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "optional": true, - "requires": { - "inherits": "~2.0.0" - } - }, "bluebird": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", - "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" - }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1261,262 +2890,73 @@ } } }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "browserfs": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/browserfs/-/browserfs-1.4.3.tgz", - "integrity": "sha512-tz8HClVrzTJshcyIu8frE15cjqjcBIu15Bezxsvl/i+6f59iNCN3kznlWjz0FEb3DlnDx3gW5szxeT6D1x0s0w==", - "dev": true, - "requires": { - "async": "^2.1.4", - "pako": "^1.0.4" - } - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sha3": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.1.tgz", - "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", - "requires": { - "js-sha3": "^0.3.1" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } - }, - "bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "dev": true, - "optional": true, - "requires": { - "base-x": "^3.0.2" - } - }, - "bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, - "optional": true, - "requires": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, - "optional": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "optional": true - }, - "buffer-fill": { + "btoa-lite": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", "dev": true }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "buffer-xor": { + "builtins": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", "dev": true }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", "dev": true }, - "bytewise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", - "integrity": "sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4=", - "requires": { - "bytewise-core": "^1.2.2", - "typewise": "^1.0.3" - } - }, - "bytewise-core": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", - "integrity": "sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI=", - "requires": { - "typewise-core": "^1.2" - } + "byte-size": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-5.0.1.tgz", + "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==", + "dev": true }, "cacache": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" }, "dependencies": { - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "glob": "^7.1.3" } - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true } } }, @@ -1537,55 +2977,142 @@ "unset-value": "^1.0.0" } }, - "cachedown": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cachedown/-/cachedown-1.0.0.tgz", - "integrity": "sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU=", + "caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, "requires": { - "abstract-leveldown": "^2.4.1", - "lru-cache": "^3.2.0" + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" }, "dependencies": { - "abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, "requires": { - "xtend": "~4.0.0" + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } } } }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true }, "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.1.0.tgz", + "integrity": "sha512-WCMml9ivU60+8rEJgELlFp1gxFcEGxwYleE3bziHEDeqsqAWGHdimB7beBFGjLzVNgPGyDsfgXLQEYMpmIFnVQ==", + "dev": true }, - "caniuse-lite": { - "version": "1.0.30000892", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000892.tgz", - "integrity": "sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w==" + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true }, "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "chardet": { @@ -1594,58 +3121,68 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "checkpoint-store": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", - "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", - "requires": { - "functional-red-black-tree": "^1.0.1" - } - }, "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } } }, "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, - "chrome-trace-event": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", - "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true }, "class-utils": { "version": "0.3.6", @@ -1665,70 +3202,278 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-highlight": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.4.tgz", + "integrity": "sha512-s7Zofobm20qriqDoU9sXptQx0t2R9PEgac92mENNm7xaEe1hn71IIMsXMK+6encA6WRCWWxIGQbipr3q998tlQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "highlight.js": "^9.6.0", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^5.1.1", + "yargs": "^15.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" } } } }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" } }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "coinstring": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/coinstring/-/coinstring-2.3.0.tgz", - "integrity": "sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q=", - "dev": true, - "optional": true, - "requires": { - "bs58": "^2.0.1", - "create-hash": "^1.1.1" - }, - "dependencies": { - "bs58": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.1.tgz", - "integrity": "sha1-VZCNWPGYKrogCPob7Y+RmYopv40=", - "dev": true, - "optional": true - } - } + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true }, "collection-visit": { "version": "1.0.0", @@ -1755,21 +3500,23 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "columnify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", + "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" } }, - "commander": { - "version": "2.8.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "requires": { - "graceful-readlink": ">= 1.0.0" + "delayed-stream": "~1.0.0" } }, "commondir": { @@ -1778,80 +3525,369 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + }, + "dependencies": { + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + } + } + }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", "dev": true, "requires": { - "date-now": "^0.1.4" + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "conventional-changelog-angular": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.11.tgz", + "integrity": "sha512-nSLypht/1yEflhuTogC03i7DX7sOrXGsRn14g131Potqi6cbGbGEE9PSDEHKldabB6N76HiSyw9Ph+kLmC04Qw==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + } }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "conventional-changelog-core": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz", + "integrity": "sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ==", + "dev": true, + "requires": { + "conventional-changelog-writer": "^4.0.6", + "conventional-commits-parser": "^3.0.3", + "dateformat": "^3.0.0", + "get-pkg-repo": "^1.0.0", + "git-raw-commits": "2.0.0", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^2.0.3", + "lodash": "^4.2.1", + "normalize-package-data": "^2.3.5", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-changelog-preset-loader": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", "dev": true }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "conventional-changelog-writer": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.17.tgz", + "integrity": "sha512-IKQuK3bib/n032KWaSb8YlBFds+aLmzENtnKtxJy3+HqDq5kohu3g/UdNbIHeJWygfnEbZjnCKFxAW0y7ArZAw==", + "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "compare-func": "^2.0.0", + "conventional-commits-filter": "^2.0.6", + "dateformat": "^3.0.0", + "handlebars": "^4.7.6", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^7.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + } } }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true + "conventional-commits-filter": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.6.tgz", + "integrity": "sha512-4g+sw8+KA50/Qwzfr0hL5k5NWxqtrOVw4DDk3/h6L85a9Gz0/Eqp3oP+CWCNfesBvZZZEFHF7OTEbRe+yYSyKw==", + "dev": true, + "requires": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + } }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "conventional-commits-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.1.0.tgz", + "integrity": "sha512-RSo5S0WIwXZiRxUGTPuYFbqvrR4vpJ1BDdTlthFgvHt5kEdnd1+pdvwWphWn57/oIl4V72NMmOocFqqJ8mFFhA==", + "dev": true, + "requires": { + "JSONStream": "^1.0.4", + "is-text-path": "^1.0.1", + "lodash": "^4.17.15", + "meow": "^7.0.0", + "split2": "^2.0.0", + "through2": "^3.0.0", + "trim-off-newlines": "^1.0.0" + }, + "dependencies": { + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + } + } }, - "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true + "conventional-recommended-bump": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-5.0.1.tgz", + "integrity": "sha512-RVdt0elRcCxL90IrNP0fYCpq1uGt2MALko0eyeQ+zQuDVWtMGAy9ng6yYn3kax42lCj9+XBxQ8ZN6S9bdKxDhQ==", + "dev": true, + "requires": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.1.1", + "conventional-commits-filter": "^2.0.2", + "conventional-commits-parser": "^3.0.3", + "git-raw-commits": "2.0.0", + "git-semver-tags": "^2.0.3", + "meow": "^4.0.0", + "q": "^1.5.1" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } }, "copy-concurrently": { "version": "1.0.5", @@ -1865,6 +3901,17 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "copy-descriptor": { @@ -1873,330 +3920,182 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cors": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", - "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", - "dev": true, - "requires": { - "object-assign": "^4", - "vary": "^1" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", "dev": true, "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" } }, "cross-env": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz", - "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz", + "integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==", "dev": true, "requires": { - "cross-spawn": "^6.0.5", - "is-windows": "^1.0.0" - } - }, - "cross-fetch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.2.tgz", - "integrity": "sha1-pH/09/xxLauo9qaVoRyUhEDUVyM=", - "requires": { - "node-fetch": "2.1.2", - "whatwg-fetch": "2.0.4" + "cross-spawn": "^7.0.1" } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "array-find-index": "^1.0.1" } }, "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, + "dargs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", + "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, "requires": { "assert-plus": "^1.0.0" } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, "requires": { "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "dev": true + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, - "decompress": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", - "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", "dev": true, - "optional": true, "requires": { - "decompress-tar": "^4.0.0", - "decompress-tarbz2": "^4.0.0", - "decompress-targz": "^4.0.0", - "decompress-unzip": "^4.0.1", - "graceful-fs": "^4.1.10", - "make-dir": "^1.0.0", - "pify": "^2.3.0", - "strip-dirs": "^2.0.0" + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" }, "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "optional": true + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true } } }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true }, - "decompress-tar": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", - "dev": true, - "requires": { - "file-type": "^5.2.0", - "is-stream": "^1.1.0", - "tar-stream": "^1.5.2" - } + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true }, - "decompress-tarbz2": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", "dev": true, - "optional": true, "requires": { - "decompress-tar": "^4.1.0", - "file-type": "^6.1.0", - "is-stream": "^1.1.0", - "seek-bzip": "^1.0.5", - "unbzip2-stream": "^1.0.9" + "strip-bom": "^4.0.0" }, "dependencies": { - "file-type": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", - "dev": true, - "optional": true + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true } } }, - "decompress-targz": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", - "dev": true, - "optional": true, - "requires": { - "decompress-tar": "^4.1.1", - "file-type": "^5.2.0", - "is-stream": "^1.1.0" - } - }, - "decompress-unzip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, - "optional": true, - "requires": { - "file-type": "^3.8.0", - "get-stream": "^2.2.0", - "pify": "^2.3.0", - "yauzl": "^2.4.2" - }, - "dependencies": { - "file-type": { - "version": "3.9.0", - "resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true, - "optional": true - }, - "get-stream": { - "version": "2.3.1", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", - "dev": true, - "optional": true, - "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "optional": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "optional": true - } - } - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" - }, - "deferred-leveldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", "requires": { - "abstract-leveldown": "~2.6.0" - }, - "dependencies": { - "abstract-leveldown": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", - "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "requires": { - "xtend": "~4.0.0" - } - } + "clone": "^1.0.2" } }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" }, "dependencies": { "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true } } }, @@ -2241,763 +4140,328 @@ } } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "des.js": { + "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "requires": { - "repeating": "^2.0.0" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "drbg.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", - "requires": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "duplexify": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.79", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.79.tgz", - "integrity": "sha512-LQdY3j4PxuUl6xfxiFruTSlCniTrTrzAd8/HfsLEMi0PUpaQ0Iy+Pr4N4VllDYjs0Hyu2lkTbvzqlG+PX9NsNw==" - }, - "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "encoding-down": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", - "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", - "requires": { - "abstract-leveldown": "^5.0.0", - "inherits": "^2.0.3", - "level-codec": "^9.0.0", - "level-errors": "^2.0.0", - "xtend": "^4.0.1" - }, - "dependencies": { - "abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "requires": { - "xtend": "~4.0.0" - } - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" - } - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", - "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, - "eth-block-tracker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz", - "integrity": "sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug==", - "requires": { - "eth-query": "^2.1.0", - "ethereumjs-tx": "^1.3.3", - "ethereumjs-util": "^5.1.3", - "ethjs-util": "^0.1.3", - "json-rpc-engine": "^3.6.0", - "pify": "^2.3.0", - "tape": "^4.6.3" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } + "detect-indent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", + "dev": true }, - "eth-json-rpc-infura": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.1.2.tgz", - "integrity": "sha512-IuK5Iowfs6taluA/3Okmu6EfZcFMq6MQuyrUL1PrCoJstuuBr3TvVeSy3keDyxfbrjFB34nCo538I8G+qMtsbw==", + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dev": true, "requires": { - "cross-fetch": "^2.1.1", - "eth-json-rpc-middleware": "^1.5.0", - "json-rpc-engine": "^3.4.0", - "json-rpc-error": "^2.0.0", - "tape": "^4.8.0" + "asap": "^2.0.0", + "wrappy": "1" } }, - "eth-json-rpc-middleware": { - "version": "1.6.0", - "resolved": "http://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", - "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", - "requires": { - "async": "^2.5.0", - "eth-query": "^2.1.2", - "eth-tx-summary": "^3.1.2", - "ethereumjs-block": "^1.6.0", - "ethereumjs-tx": "^1.3.3", - "ethereumjs-util": "^5.1.2", - "ethereumjs-vm": "^2.1.0", - "fetch-ponyfill": "^4.0.0", - "json-rpc-engine": "^3.6.0", - "json-rpc-error": "^2.0.0", - "json-stable-stringify": "^1.0.1", - "promise-to-callback": "^1.0.0", - "tape": "^4.6.3" - }, - "dependencies": { - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" - }, - "ethereumjs-block": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", - "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "requires": { - "async": "^2.0.1", - "ethereum-common": "0.2.0", - "ethereumjs-tx": "^1.2.2", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - } - } + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true }, - "eth-lib": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", - "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", "dev": true, "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "keccakjs": "^0.2.1", - "nano-json-stream-parser": "^0.1.2", - "servify": "^0.1.12", - "ws": "^3.0.0", - "xhr-request-promise": "^0.1.2" + "path-type": "^3.0.0" } }, - "eth-query": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", - "integrity": "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=", + "dot-prop": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", + "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", + "dev": true, "requires": { - "json-rpc-random-id": "^1.0.0", - "xtend": "^4.0.1" + "is-obj": "^1.0.0" } }, - "eth-sig-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.0.2.tgz", - "integrity": "sha512-tB6E8jf/aZQ943bo3+iojl8xRe3Jzcl+9OT6v8K7kWis6PdIX19SB2vYvN849cB9G9m/XLjYFK381SgdbsnpTA==", - "requires": { - "ethereumjs-abi": "0.6.5", - "ethereumjs-util": "^5.1.1" - } + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true }, - "eth-tx-summary": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.3.tgz", - "integrity": "sha512-1gZpA5fKarJOVSb5OUlPnhDQuIazqAkI61zlVvf5LdG47nEgw+/qhyZnuj3CUdE/TLTKuRzPLeyXLjaB4qWTRQ==", + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, "requires": { - "async": "^2.1.2", - "bn.js": "^4.11.8", - "clone": "^2.0.0", - "concat-stream": "^1.5.1", - "end-of-stream": "^1.1.0", - "eth-query": "^2.0.2", - "ethereumjs-block": "^1.4.1", - "ethereumjs-tx": "^1.1.1", - "ethereumjs-util": "^5.0.1", - "ethereumjs-vm": "2.3.4", - "through2": "^2.0.3", - "treeify": "^1.0.1", - "web3-provider-engine": "^13.3.2" - }, - "dependencies": { - "eth-block-tracker": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz", - "integrity": "sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA==", - "requires": { - "async-eventemitter": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", - "eth-query": "^2.1.0", - "ethereumjs-tx": "^1.3.3", - "ethereumjs-util": "^5.1.3", - "ethjs-util": "^0.1.3", - "json-rpc-engine": "^3.6.0", - "pify": "^2.3.0", - "tape": "^4.6.3" - }, - "dependencies": { - "async-eventemitter": { - "version": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", - "from": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", - "requires": { - "async": "^2.4.0" - } - } - } - }, - "eth-sig-util": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", - "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", - "requires": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", - "ethereumjs-util": "^5.1.1" - } - }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" - }, - "ethereumjs-abi": { - "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", - "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", - "requires": { - "bn.js": "^4.10.0", - "ethereumjs-util": "^5.0.0" - } - }, - "ethereumjs-block": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", - "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "requires": { - "async": "^2.0.1", - "ethereum-common": "0.2.0", - "ethereumjs-tx": "^1.2.2", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - }, - "ethereumjs-vm": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.4.tgz", - "integrity": "sha512-Y4SlzNDqxrCO58jhp98HdnZVdjOqB+HC0hoU+N/DEp1aU+hFkRX/nru5F7/HkQRPIlA6aJlQp/xIA6xZs1kspw==", - "requires": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", - "ethereum-common": "0.2.0", - "ethereumjs-account": "^2.0.3", - "ethereumjs-block": "~1.7.0", - "ethereumjs-util": "^5.1.3", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.1.2", - "rustbn.js": "~0.1.1", - "safe-buffer": "^5.1.1" - } + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true }, - "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "rustbn.js": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.1.2.tgz", - "integrity": "sha512-bAkNqSHYdJdFsBC7Z11JgzYktL31HIpB2o70jZcGiL1U1TVtPyvaVhDrGWwS8uZtaqwW2k6NOPGZCqW/Dgh5Lg==" - }, - "solc": { - "version": "0.4.25", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.25.tgz", - "integrity": "sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg==", - "requires": { - "fs-extra": "^0.30.0", - "memorystream": "^0.3.1", - "require-from-string": "^1.1.0", - "semver": "^5.3.0", - "yargs": "^4.7.1" - } + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, - "web3-provider-engine": { - "version": "13.8.0", - "resolved": "http://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz", - "integrity": "sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "requires": { - "async": "^2.5.0", - "clone": "^2.0.0", - "eth-block-tracker": "^2.2.2", - "eth-sig-util": "^1.4.2", - "ethereumjs-block": "^1.2.2", - "ethereumjs-tx": "^1.2.0", - "ethereumjs-util": "^5.1.1", - "ethereumjs-vm": "^2.0.2", - "fetch-ponyfill": "^4.0.0", - "json-rpc-error": "^2.0.0", - "json-stable-stringify": "^1.0.1", - "promise-to-callback": "^1.0.0", - "readable-stream": "^2.2.9", - "request": "^2.67.0", - "semaphore": "^1.0.3", - "solc": "^0.4.2", - "tape": "^4.4.0", - "xhr": "^2.2.0", - "xtend": "^4.0.1" + "safe-buffer": "~5.1.0" } } } }, - "ethereum-common": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.16.tgz", - "integrity": "sha1-mh4Wnq00q3XgifUMpRK/0PvRJlU=" - }, - "ethereumjs-abi": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", - "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, "requires": { - "bn.js": "^4.10.0", - "ethereumjs-util": "^4.3.0" - }, - "dependencies": { - "ethereumjs-util": { - "version": "4.5.0", - "resolved": "http://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", - "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", - "requires": { - "bn.js": "^4.8.0", - "create-hash": "^1.1.2", - "keccakjs": "^0.2.0", - "rlp": "^2.0.0", - "secp256k1": "^3.0.1" - } - } + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "ethereumjs-account": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", - "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", - "requires": { - "ethereumjs-util": "^5.0.0", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true }, - "ethereumjs-block": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.2.2.tgz", - "integrity": "sha1-LsdTSlkCG47JuDww5JaQxuuu3aE=", + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, "requires": { - "async": "^1.5.2", - "ethereum-common": "0.0.16", - "ethereumjs-tx": "^1.0.0", - "ethereumjs-util": "^4.0.1", - "merkle-patricia-tree": "^2.1.2" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - }, - "ethereumjs-util": { - "version": "4.5.0", - "resolved": "http://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", - "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", - "requires": { - "bn.js": "^4.8.0", - "create-hash": "^1.1.2", - "keccakjs": "^0.2.0", - "rlp": "^2.0.0", - "secp256k1": "^3.0.1" - } - } + "iconv-lite": "^0.6.2" } }, - "ethereumjs-common": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz", - "integrity": "sha512-ywYGsOeGCsMNWso5Y4GhjWI24FJv9FK7+VyVKiQgXg8ZRDPXJ7F/kJ1CnjtkjTvDF4e0yqU+FWswlqR3bmZQ9Q==" - }, - "ethereumjs-tx": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.4.tgz", - "integrity": "sha512-kOgUd5jC+0tgV7t52UDECMMz9Uf+Lro+6fSpCvzWemtXfMEcwI3EOxf5mVPMRbTFkMMhuERokNNVF3jItAjidg==", + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "requires": { - "ethereum-common": "^0.0.18", - "ethereumjs-util": "^5.0.0" - }, - "dependencies": { - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" - } + "once": "^1.4.0" } }, - "ethereumjs-util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", - "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", - "requires": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "ethjs-util": "^0.1.3", - "keccak": "^1.0.2", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" - } + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "dev": true }, - "ethereumjs-vm": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz", - "integrity": "sha512-MJ4lCWa5c6LhahhhvoDKW+YGjK00ZQn0RHHLh4L+WaH1k6Qv7/q3uTluew6sJGNCZdlO0yYMDXYW9qyxLHKlgQ==", - "requires": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", - "ethereumjs-account": "^2.0.3", - "ethereumjs-block": "~1.7.0", - "ethereumjs-common": "~0.4.0", - "ethereumjs-util": "^5.2.0", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.1.2", - "rustbn.js": "~0.2.0", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" - }, - "ethereumjs-block": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", - "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "requires": { - "async": "^2.0.1", - "ethereum-common": "0.2.0", - "ethereumjs-tx": "^1.2.2", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" - } - } - } + "envinfo": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.3.tgz", + "integrity": "sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==", + "dev": true }, - "ethereumjs-wallet": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz", - "integrity": "sha512-DHEKPV9lYORM7dL8602dkb+AgdfzCYz2lxpdYQoD3OwG355LLDuivW9rGuLpDMCry/ORyBYV6n+QCo/71SwACg==", + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, - "optional": true, "requires": { - "aes-js": "^3.1.1", - "bs58check": "^2.1.2", - "ethereumjs-util": "^5.2.0", - "hdkey": "^1.0.0", - "safe-buffer": "^5.1.2", - "scrypt.js": "^0.2.0", - "utf8": "^3.0.0", - "uuid": "^3.3.2" + "is-arrayish": "^0.2.1" } }, - "ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", "dev": true, "requires": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" }, "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true } } }, - "ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, - "eventemitter3": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", - "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=", + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, - "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" + "es6-promise": "^4.0.3" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "expand-brackets": { @@ -3041,60 +4505,11 @@ "requires": { "is-extendable": "^0.1.0" } - } - } - }, - "express": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", - "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.3", - "content-disposition": "0.5.2", - "content-type": "~1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.1.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.4", - "qs": "6.5.2", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.2", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } @@ -3102,7 +4517,8 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extend-shallow": { "version": "3.0.2", @@ -3126,9 +4542,9 @@ } }, "external-editor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "requires": { "chardet": "^0.7.0", @@ -3144,6 +4560,15 @@ "requires": { "safer-buffer": ">= 2.1.2 < 3" } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } } } }, @@ -3215,55 +4640,64 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fake-merkle-patricia-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", - "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", - "requires": { - "checkpoint-store": "^1.1.0" - } + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", "dev": true, - "optional": true, "requires": { - "pend": "~1.2.0" - } - }, - "fetch-ponyfill": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", - "integrity": "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=", - "requires": { - "node-fetch": "~1.7.1" + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" }, "dependencies": { - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } } } } }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -3273,18 +4707,6 @@ "escape-string-regexp": "^1.0.5" } }, - "file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", - "dev": true - }, - "filesize": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", - "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", - "dev": true - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -3308,74 +4730,147 @@ } } }, - "finalhandler": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", "dev": true, "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "ms": "2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" } }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" + "locate-path": "^3.0.0" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "semver-regex": "^2.0.0" } }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", "dev": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - } - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "for-in": { @@ -3384,27 +4879,33 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, + "foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true }, "form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -3414,12 +4915,6 @@ "map-cache": "^0.2.2" } }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -3428,35 +4923,77 @@ "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "fromentries": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", + "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==", + "dev": true + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", "dev": true }, "fs-extra": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", - "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" } }, - "fs-promise": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-2.0.3.tgz", - "integrity": "sha1-9k5PhUvPaJqovdy6JokW2z20aFQ=", + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, - "optional": true, "requires": { - "any-promise": "^1.3.0", - "fs-extra": "^2.0.0", - "mz": "^2.6.0", - "thenify-all": "^1.6.0" + "minipass": "^2.6.0" } }, "fs-write-stream-atomic": { @@ -3469,593 +5006,614 @@ "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" }, "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { + "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, - "optional": true, "requires": { - "ms": "2.0.0" + "safe-buffer": "~5.1.0" } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-pkg-repo": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", + "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "meow": "^3.3.0", + "normalize-package-data": "^2.3.0", + "parse-github-repo-url": "^1.3.0", + "through2": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, - "optional": true, "requires": { - "minipass": "^2.2.1" + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" } }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, - "optional": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, - "glob": { - "version": "7.1.2", - "bundled": true, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, - "optional": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "repeating": "^2.0.0" } }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, - "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" } }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, - "optional": true, "requires": { - "minimatch": "^3.0.4" + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" } }, - "inflight": { - "version": "1.0.6", - "bundled": true, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, - "optional": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "error-ex": "^1.2.0" } }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "pinkie-promise": "^2.0.0" } }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, - "minimist": { - "version": "0.0.8", - "bundled": true, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { + "read-pkg": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, - "optional": true, "requires": { - "minipass": "^2.2.1" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" } }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "minimist": "0.0.8" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" } }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, - "optional": true, "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" } }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, - "optional": true, "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" + "is-utf8": "^0.2.0" } }, - "nopt": { - "version": "4.0.1", - "bundled": true, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, - "optional": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "get-stdin": "^4.0.1" } }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + } + } + }, + "get-port": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", + "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "git-config-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz", + "integrity": "sha1-bTP37WPbDQ4RgTFQO6s6ykfVRmQ=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "fs-exists-sync": "^0.1.0", + "homedir-polyfill": "^1.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, - "optional": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "is-extendable": "^0.1.0" } + } + } + }, + "git-raw-commits": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", + "integrity": "sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==", + "dev": true, + "requires": { + "dargs": "^4.0.1", + "lodash.template": "^4.0.2", + "meow": "^4.0.0", + "split2": "^2.0.0", + "through2": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true }, - "npmlog": { - "version": "4.1.2", - "bundled": true, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", "dev": true, - "optional": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", "dev": true }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true }, - "once": { - "version": "1.4.0", - "bundled": true, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", "dev": true, "requires": { - "wrappy": "1" + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" } }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", "dev": true, - "optional": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" } }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true }, - "process-nextick-args": { + "redent": { "version": "2.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" } }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true }, - "rimraf": { - "version": "2.6.2", - "bundled": true, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + } + } + }, + "git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "requires": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "git-semver-tags": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-2.0.3.tgz", + "integrity": "sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA==", + "dev": true, + "requires": { + "meow": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", "dev": true, - "optional": true, "requires": { - "glob": "^7.0.5" + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" } }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", "dev": true }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { + "map-obj": { "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", "dev": true, - "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" } }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true }, - "tar": { - "version": "4.4.1", - "bundled": true, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", "dev": true, - "optional": true, "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" } }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true }, - "wrappy": { - "version": "1.0.2", - "bundled": true, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", "dev": true }, - "yallist": { - "version": "3.0.2", - "bundled": true, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", "dev": true } } }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "git-up": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.2.tgz", + "integrity": "sha512-kbuvus1dWQB2sSW4cbfTeGpCMd8ge9jx9RKnhXhuJ7tnvT+NIrTVfYZxjtflZddQYcmdOTlkAcjmx7bor+15AQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" + "is-ssh": "^1.3.0", + "parse-url": "^5.0.0" } }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" - }, - "get-stream": { - "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "git-url-parse": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.2.0.tgz", + "integrity": "sha512-KPoHZg8v+plarZvto4ruIzzJLFQoRx+sUs5DQSr07By9IBKguVd+e6jwrFR6/TP6xrCJlNV1tPqLO1aREc7O2g==", + "dev": true, + "requires": { + "git-up": "^4.0.0" + } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "git-user-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-user-name/-/git-user-name-2.0.0.tgz", + "integrity": "sha512-1DC8rUNm2I5V9v4eIpK6PSjKCp9bI0t6Wl05WSk+xEMS8GhR8GWzxM3aGZfPrfuqEfWxSbui5/pQJryJFXqCzQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "git-config-path": "^1.0.1", + "parse-git-config": "^1.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", + "dev": true, "requires": { - "assert-plus": "^1.0.0" + "ini": "^1.3.2" } }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4066,77 +5624,46 @@ } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "requires": { - "min-document": "^2.19.0", - "process": "~0.5.1" + "is-glob": "^4.0.1" } }, - "global-modules-path": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz", - "integrity": "sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==", + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", "dev": true }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true }, - "got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", "dev": true, "requires": { - "decompress-response": "^3.2.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-plain-obj": "^1.1.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "p-cancelable": "^0.3.0", - "p-timeout": "^1.1.1", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "url-parse-lax": "^1.0.0", - "url-to-options": "^1.0.1" + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "growl": { @@ -4145,61 +5672,75 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true }, "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, "requires": { - "ajv": "^5.3.0", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true }, - "has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "requires": { - "has-symbol-support-x": "^1.4.1" - } + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true }, "has-value": { "version": "1.0.0", @@ -4233,124 +5774,233 @@ } } }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "hash.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", - "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hdkey": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-1.1.0.tgz", - "integrity": "sha512-E7aU8pNlWUJbXGjTz/+lKf1LkMcA3hUrC5ZleeizrmLSd++kvf8mSOe3q8CmBDA9j4hdfXO5iY6hGiTUCOV2jQ==", + "hasha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", + "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", "dev": true, - "optional": true, "requires": { - "coinstring": "^2.0.0", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "dependencies": { + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "heap": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", - "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } + "highlight.js": { + "version": "9.18.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.3.tgz", + "integrity": "sha512-zBZAmhSupHIl5sITeMqIJnYCDfAEc3Gdkqj65wC1lpI468MMQeeQkhcIAvk+RylAkxrCcI9xy9piHiXeQ1BdzQ==", + "dev": true }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" + "parse-passwd": "^1.0.0" } }, "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true }, - "http-errors": { - "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "dev": true, "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "agent-base": "4", + "debug": "3.1.0" } }, - "http-https": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", - "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=", - "dev": true - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" } }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } }, - "humanize": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz", - "integrity": "sha1-GZT/rs3+nEQe0r2sdFK3u0yeQaQ=", + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "ms": "^2.0.0" } }, - "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", - "dev": true + "husky": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", + "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } }, "iferr": { "version": "0.1.5", @@ -4358,18 +6008,46 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, - "immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } }, "import-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", - "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", "dev": true, "requires": { - "pkg-dir": "^2.0.0", + "pkg-dir": "^3.0.0", "resolve-cwd": "^2.0.0" } }, @@ -4379,44 +6057,96 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "init-package-json": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.10.3.tgz", + "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==", + "dev": true, + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + } + } }, "inquirer": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", - "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^3.0.0", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.17.10", + "lodash": "^4.17.12", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rxjs": "^6.1.0", + "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.1.0", "through": "^2.3.6" }, "dependencies": { @@ -4426,19 +6156,10 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4446,6 +6167,12 @@ "supports-color": "^5.3.0" } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -4460,15 +6187,34 @@ "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } } }, "supports-color": { @@ -4482,38 +6228,26 @@ } } }, - "intercept-require": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/intercept-require/-/intercept-require-1.1.0.tgz", - "integrity": "sha1-6OJAnUrbJTXDGn5KBc9gzadE9mU=", - "requires": { - "callsite": "^1.0.0", - "object-assign": "^2.0.0" - } - }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "into-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", + "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "dev": true, "requires": { - "loose-envify": "^1.0.0" + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, - "ipaddr.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, "is-accessor-descriptor": { @@ -4539,15 +6273,16 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true }, "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "^2.0.0" } }, "is-buffer": { @@ -4556,19 +6291,21 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, "requires": { - "builtin-modules": "^1.0.0" + "ci-info": "^2.0.0" } }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" - }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -4590,9 +6327,10 @@ } }, "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true }, "is-descriptor": { "version": "0.1.6", @@ -4613,6 +6351,12 @@ } } }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -4626,51 +6370,34 @@ "dev": true }, "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-fn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz", - "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, "requires": { "number-is-nan": "^1.0.0" } }, - "is-function": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", - "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" - }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, - "is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" - }, - "is-natural-number": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", - "dev": true, - "optional": true + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true }, "is-number": { "version": "3.0.0", @@ -4692,10 +6419,10 @@ } } }, - "is-object": { + "is-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, "is-plain-obj": { @@ -4713,48 +6440,59 @@ "isobject": "^3.0.1" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, "requires": { - "has": "^1.0.1" + "has-symbols": "^1.0.1" } }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true + "is-ssh": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.2.tgz", + "integrity": "sha512-elEw0/0c2UscLrNG+OAorbP539E3rhliKPg+hDMWN9VwrDXfYK+4PBEykDPfxlYYtQvl84TascnQyobfQLHEhQ==", + "dev": true, + "requires": { + "protocols": "^1.1.0" + } }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, "requires": { - "has-symbols": "^1.0.0" + "text-extensions": "^1.0.0" } }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true }, "is-windows": { "version": "1.0.2", @@ -4762,11 +6500,6 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4782,434 +6515,428 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - } - }, - "js-sha3": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.3.1.tgz", - "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=" - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "json-rpc-engine": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz", - "integrity": "sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA==", - "requires": { - "async": "^2.0.1", - "babel-preset-env": "^1.7.0", - "babelify": "^7.3.0", - "json-rpc-error": "^2.0.0", - "promise-to-callback": "^1.0.0", - "safe-event-emitter": "^1.0.1" - } - }, - "json-rpc-error": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/json-rpc-error/-/json-rpc-error-2.0.0.tgz", - "integrity": "sha1-p6+cICg4tekFxyUOVH8a/3cligI=", - "requires": { - "inherits": "^2.0.1" - } - }, - "json-rpc-random-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", - "integrity": "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json5": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "keccak": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", - "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", - "requires": { - "bindings": "^1.2.1", - "inherits": "^2.0.3", - "nan": "^2.2.1", - "safe-buffer": "^5.1.0" - } - }, - "keccakjs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", - "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", - "requires": { - "browserify-sha3": "^0.0.1", - "sha3": "^1.1.0" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", "dev": true }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "requires": { - "graceful-fs": "^4.1.9" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, "requires": { - "invert-kv": "^1.0.0" + "append-transform": "^2.0.0" } }, - "level-codec": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.0.tgz", - "integrity": "sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg==" - }, - "level-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", - "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, "requires": { - "errno": "~0.1.1" + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "level-iterator-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", - "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, "requires": { - "inherits": "^2.0.1", - "level-errors": "^1.0.3", - "readable-stream": "^1.0.33", - "xtend": "^4.0.0" + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" }, "dependencies": { - "level-errors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.1.2.tgz", - "integrity": "sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w==", + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "requires": { - "errno": "~0.1.1" + "semver": "^6.0.0" } }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "aggregate-error": "^3.0.0" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, - "level-post": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/level-post/-/level-post-1.0.7.tgz", - "integrity": "sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew==", + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, "requires": { - "ltgt": "^2.1.2" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "level-sublevel": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/level-sublevel/-/level-sublevel-6.6.4.tgz", - "integrity": "sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA==", + "istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, "requires": { - "bytewise": "~1.1.0", - "level-codec": "^9.0.0", - "level-errors": "^2.0.0", - "level-iterator-stream": "^2.0.3", - "ltgt": "~2.1.1", - "pull-defer": "^0.2.2", - "pull-level": "^2.0.3", - "pull-stream": "^3.6.8", - "typewiselite": "~1.0.0", - "xtend": "~4.0.0" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "dependencies": { - "level-iterator-stream": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", - "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.5", - "xtend": "^4.0.0" + "ms": "2.1.2" } }, - "ltgt": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz", - "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=" + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, - "level-ws": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", - "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, "requires": { - "readable-stream": "~1.0.15", - "xtend": "~2.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "requires": { - "object-keys": "~0.4.0" - } - } + "minimist": "^1.2.5" } }, - "levelup": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", - "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", + "jsonfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", + "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "dev": true, "requires": { - "deferred-leveldown": "~4.0.0", - "level-errors": "~2.0.0", - "level-iterator-stream": "~3.0.0", - "xtend": "~4.0.0" - }, - "dependencies": { - "abstract-leveldown": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", - "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", - "requires": { - "xtend": "~4.0.0" - } - }, - "deferred-leveldown": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", - "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", - "requires": { - "abstract-leveldown": "~5.0.0", - "inherits": "^2.0.3" - } - }, - "level-iterator-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.0.tgz", - "integrity": "sha512-2tpBjsNZtvST8eJIy3R9Sk13aC84omgqvT4sQObZaUb4hDyDe4woWAMudXX3eCsaydOGVaaI5WMpRRBFSzz5WA==", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.5", - "xtend": "^4.0.0" - } - } + "graceful-fs": "^4.1.6", + "universalify": "^1.0.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" } }, - "loader-runner": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", - "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "lerna": { + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-3.22.1.tgz", + "integrity": "sha512-vk1lfVRFm+UuEFA7wkLKeSF7Iz13W+N/vFd48aW2yuS7Kv0RbNm2/qcDPV863056LMfkRlsEe+QYOw3palj5Lg==", + "dev": true, + "requires": { + "@lerna/add": "3.21.0", + "@lerna/bootstrap": "3.21.0", + "@lerna/changed": "3.21.0", + "@lerna/clean": "3.21.0", + "@lerna/cli": "3.18.5", + "@lerna/create": "3.22.0", + "@lerna/diff": "3.21.0", + "@lerna/exec": "3.21.0", + "@lerna/import": "3.22.0", + "@lerna/info": "3.21.0", + "@lerna/init": "3.21.0", + "@lerna/link": "3.21.0", + "@lerna/list": "3.21.0", + "@lerna/publish": "3.22.1", + "@lerna/run": "3.21.0", + "@lerna/version": "3.22.1", + "import-local": "^2.0.0", + "npmlog": "^4.1.2" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", "dev": true, "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "p-locate": "^2.0.0", + "p-locate": "^3.0.0", "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, - "lodash.merge": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", - "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, - "long": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", - "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, - "looper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz", - "integrity": "sha1-Zs0Md0rz1P7axTeU90LbVtqPCew=" + "lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", + "dev": true }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" } }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, "lru-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", - "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "requires": { - "pseudomap": "^1.0.1" + "yallist": "^3.0.2" } }, - "ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" + "macos-release": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.4.1.tgz", + "integrity": "sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg==", + "dev": true }, "make-dir": { "version": "1.3.0", @@ -5228,19 +6955,29 @@ } } }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "map-age-cleaner": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz", - "integrity": "sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==", + "make-fetch-happen": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", "dev": true, "requires": { - "p-defer": "^1.0.0" + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" } }, "map-cache": { @@ -5249,6 +6986,12 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", + "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -5258,152 +7001,144 @@ "object-visit": "^1.0.0" } }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" - } - }, - "memdown": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.3.1.tgz", - "integrity": "sha512-Qr0bqzSQWUEU0/nwSOOo3j7Gt/I3lKUoUENmsZiJ7YZoPtt0WrfV4h1Qbv/XurwBCN9qt3zR68Vfk0iY5cBDSQ==", + "meow": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz", + "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==", "dev": true, "requires": { - "abstract-leveldown": "2.7.0", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^2.5.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.13.1", + "yargs-parser": "^18.1.3" }, "dependencies": { - "abstract-leveldown": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.0.tgz", - "integrity": "sha512-maam3ZrTeORbXKEJUeJZkYOsorEwr060WitXuQlUuIFlg0RofyyHts49wtaVmShJ6l0wEWB0ZtPhf6QYBA7D2w==", + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "xtend": "~4.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } - } - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merkle-patricia-tree": { - "version": "2.3.1", - "resolved": "http://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", - "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", - "requires": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", - "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" - }, - "dependencies": { - "abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "requires": { - "xtend": "~4.0.0" + "p-locate": "^4.1.0" } }, - "async": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } }, - "level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true }, - "level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, "requires": { - "errno": "~0.1.1" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } } }, - "levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, "requires": { - "deferred-leveldown": "~1.2.1", - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "level-iterator-stream": "~1.3.0", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, - "memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, "requires": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, "micromatch": { @@ -5427,33 +7162,19 @@ "to-regex": "^3.0.2" } }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true }, "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, "requires": { - "mime-db": "~1.36.0" + "mime-db": "1.44.0" } }, "mimic-fn": { @@ -5462,47 +7183,61 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, - "mimic-response": { + "min-indent": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "requires": { - "dom-walk": "^0.1.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "requires": { + "minipass": "^2.9.0" + } }, "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, "requires": { "concat-stream": "^1.5.0", @@ -5511,16 +7246,16 @@ "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", - "pump": "^2.0.1", + "pump": "^3.0.0", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" } }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -5539,11 +7274,12 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "mkdirp-promise": { @@ -5551,74 +7287,225 @@ "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", "dev": true, - "optional": true, "requires": { "mkdirp": "*" } }, "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.0.tgz", + "integrity": "sha512-lEWEMq2LMfNJMKeuEwb5UELi+OgFDollXaytR5ggQcHpzG3NP/R7rvixAvF+9/lLsTWhWG+4yD2M70GsM06nxw==", "dev": true, "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", + "chokidar": "3.4.3", + "debug": "4.2.0", + "diff": "4.0.2", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", "growl": "1.10.5", - "he": "1.1.1", + "he": "1.2.0", + "js-yaml": "3.14.0", + "log-symbols": "4.0.0", "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "ms": "2.1.2", + "nanoid": "3.1.12", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "7.2.0", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.0.2", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "2.0.0" }, "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "ansi-regex": "^4.1.0" } }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "mock-fs": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.7.0.tgz", - "integrity": "sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA==", - "dev": true, - "optional": true + "modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true }, - "mout": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", - "integrity": "sha1-ujYR318OWx/7/QEWa48C0fX6K5k=", - "dev": true, - "optional": true + "monaco-editor": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.21.2.tgz", + "integrity": "sha512-jS51RLuzMaoJpYbu7F6TPuWpnWTLD4kjRW0+AZzcryvbxrTwhNy1KC9yboyKpgMTahpUbDUsuQULoo0GV1EPqg==", + "dev": true }, "move-concurrently": { "version": "1.0.1", @@ -5632,12 +7519,42 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, + "mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "dev": true + }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multimatch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-3.0.0.tgz", + "integrity": "sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA==", + "dev": true, + "requires": { + "array-differ": "^2.0.3", + "array-union": "^1.0.2", + "arrify": "^1.0.1", + "minimatch": "^3.0.4" + } }, "mute-stream": { "version": "0.0.7", @@ -5650,31 +7567,16 @@ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dev": true, - "optional": true, "requires": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "optional": true - } } }, - "nan": { - "version": "2.10.0", - "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" - }, - "nano-json-stream-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", + "nanoid": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", + "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", "dev": true }, "nanomatch": { @@ -5696,16 +7598,10 @@ "to-regex": "^3.0.1" } }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - }, "neo-async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "nice-try": { @@ -5715,142 +7611,505 @@ "dev": true }, "node-fetch": { - "version": "2.1.2", - "resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "buffer": { - "version": "4.9.1", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "events": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "node-fetch-npm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", + "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-gyp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.1.tgz", + "integrity": "sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==", + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.1.2", + "request": "^2.88.0", + "rimraf": "^2.6.3", + "semver": "^5.7.1", + "tar": "^4.4.12", + "which": "^1.3.1" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "requires": { + "process-on-spawn": "^1.0.0" + } + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-lifecycle": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz", + "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==", + "dev": true, + "requires": { + "byline": "^5.0.0", + "graceful-fs": "^4.1.15", + "node-gyp": "^5.0.2", + "resolve-from": "^4.0.0", + "slide": "^1.1.6", + "uid-number": "0.0.6", + "umask": "^1.1.0", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "npm-package-arg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.0.tgz", + "integrity": "sha512-/ep6QDxBkm9HvOhOg0heitSd7JHA1U7y1qhhlRlteYYAi9Pdb/ZV7FW5aHpkrpM8+P+4p/jjR8zCyKPBMBjSig==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "semver": "^7.0.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", + "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + }, + "dependencies": { + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + }, + "dependencies": { + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + } + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "requires": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } - } - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", - "dev": true, - "requires": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true } } }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true }, "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true }, "object-copy": { "version": "0.1.0", @@ -5884,14 +8143,10 @@ } }, "object-inspect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", - "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true }, "object-visit": { "version": "1.0.1", @@ -5902,37 +8157,76 @@ "isobject": "^3.0.0" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", "dev": true, "requires": { - "isobject": "^3.0.1" + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", + "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "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.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } } }, - "oboe": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", - "integrity": "sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8=", + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", "dev": true, "requires": { - "http-https": "^1.0.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" } }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "ee-first": "1.1.1" + "isobject": "^3.0.1" } }, + "octokit-pagination-methods": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", + "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -5946,41 +8240,43 @@ "mimic-fn": "^1.0.0" } }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", "dev": true }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "os-name": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", + "dev": true, "requires": { - "lcid": "^1.0.0" + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" } }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "p-finally": { "version": "1.0.0", @@ -5989,109 +8285,246 @@ "dev": true }, "p-is-promise": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", "dev": true }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "p-try": "^1.0.0" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "^2.0.0" } }, - "p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-map-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-1.0.0.tgz", + "integrity": "sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-pipe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", + "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", + "dev": true + }, + "p-queue": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-4.0.0.tgz", + "integrity": "sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg==", "dev": true, "requires": { - "p-finally": "^1.0.0" + "eventemitter3": "^3.1.0" } }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "p-waterfall": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-1.0.0.tgz", + "integrity": "sha1-ftlLPOszMngjU69qrhGqn8I1uwA=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, + "parse-git-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-1.1.1.tgz", + "integrity": "sha1-06mYQxcTL1c5hxK7pDjhKVkN34w=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "fs-exists-sync": "^0.1.0", + "git-config-path": "^1.0.1", + "ini": "^1.3.4" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "parse-github-repo-url": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", + "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", "dev": true }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "parse-path": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.2.tgz", + "integrity": "sha512-HSqVz6iuXSiL8C1ku5Gl1Z5cwDd9Wo0q8CoffdAghP6bz8pJa1tcMC+m4N+z6VAS8QdksnIGq1TB6EgR4vPR6w==", "dev": true, "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" } }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "parse-url": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.2.tgz", + "integrity": "sha512-Czj+GIit4cdWtxo3ISZCvLiUjErSo0iI3wJ+q9Oi3QuMYTI6OZu+7cewMWZ+C1YAnKhYTk6/TLuhIgCypLthPA==", "dev": true, "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" + "is-ssh": "^1.3.0", + "normalize-url": "^3.3.0", + "parse-path": "^4.0.0", + "protocols": "^1.4.0" } }, - "parse-headers": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", - "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", - "requires": { - "for-each": "^0.3.2", - "trim": "0.0.1" - } + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "dev": true }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "parse5-htmlparser2-tree-adapter": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-5.1.1.tgz", + "integrity": "sha512-CF+TKjXqoqyDwHqBhFQ+3l5t83xYi6fVT1tQNg+Ye0JRLnTxWvIroCjEp1A0k4lneHNBGnICUf0cfYVYGEazqw==", + "dev": true, "requires": { - "error-ex": "^1.2.0" + "parse5": "^5.1.1" } }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true - }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", @@ -6099,113 +8532,95 @@ "dev": true }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "pify": "^3.0.0" }, "dependencies": { "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true } } }, - "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true, - "optional": true - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true }, "pify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.0.tgz", - "integrity": "sha512-zrSP/KDf9DH3K3VePONoCstgPiYJy9z0SCatZuTpOc7YdnWIqwkWdXOuwlr4uDc7em8QZRsFWsT/685x5InjYg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, "requires": { "pinkie": "^2.0.0" } }, "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { - "find-up": "^2.1.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } + "find-up": "^3.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" } }, "posix-character-classes": { @@ -6214,141 +8629,260 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, - "precond": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", - "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "prettier": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", "dev": true }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" - }, - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + "pretty-quick": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.0.tgz", + "integrity": "sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "promise-to-callback": { + "process-on-spawn": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz", - "integrity": "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=", - "requires": { - "is-fn": "^1.0.0", - "set-immediate-shim": "^1.0.1" - } - }, - "proxy-addr": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", - "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.8.0" + "fromentries": "^1.2.0" } }, - "prr": { + "promise-inflight": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", "dev": true, "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "pull-cat": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/pull-cat/-/pull-cat-1.1.11.tgz", - "integrity": "sha1-tkLdElXaN2pwa220+pYvX9t0wxs=" - }, - "pull-defer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/pull-defer/-/pull-defer-0.2.3.tgz", - "integrity": "sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA==" - }, - "pull-level": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pull-level/-/pull-level-2.0.4.tgz", - "integrity": "sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg==", - "requires": { - "level-post": "^1.0.7", - "pull-cat": "^1.1.9", - "pull-live": "^1.0.1", - "pull-pushable": "^2.0.0", - "pull-stream": "^3.4.0", - "pull-window": "^2.1.4", - "stream-to-pull-stream": "^1.7.1" + "err-code": "^1.0.0", + "retry": "^0.10.0" } }, - "pull-live": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pull-live/-/pull-live-1.0.1.tgz", - "integrity": "sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU=", + "promzard": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", + "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", + "dev": true, "requires": { - "pull-cat": "^1.1.9", - "pull-stream": "^3.4.0" + "read": "1" } }, - "pull-pushable": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pull-pushable/-/pull-pushable-2.2.0.tgz", - "integrity": "sha1-Xy867UethpGfAbEqLpnW8b13ZYE=" + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true }, - "pull-stream": { - "version": "3.6.9", - "resolved": "https://registry.npmjs.org/pull-stream/-/pull-stream-3.6.9.tgz", - "integrity": "sha512-hJn4POeBrkttshdNl0AoSCVjMVSuBwuHocMerUdoZ2+oIUzrWHFTwJMlbHND7OiKLVgvz6TFj8ZUVywUMXccbw==" + "protocols": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", + "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==", + "dev": true }, - "pull-window": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/pull-window/-/pull-window-2.1.4.tgz", - "integrity": "sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA=", + "protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, "requires": { - "looper": "^2.0.0" + "genfun": "^5.0.0" } }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -6364,168 +8898,229 @@ "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } } }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "query-string": { - "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true }, "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "requires": { "safe-buffer": "^5.1.0" } }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz", + "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-package-json": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz", + "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==", "dev": true, "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "glob": "^7.1.1", + "json-parse-even-better-errors": "^2.3.0", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" } }, - "randomhex": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", - "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=", - "dev": true - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "read-package-tree": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", + "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "util-promisify": "^2.1.0" } }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, "requires": { - "load-json-file": "^1.0.0", + "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "path-type": "^3.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true } } }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + "readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" } }, "regex-not": { @@ -6538,35 +9133,15 @@ "safe-regex": "^1.1.0" } }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, "requires": { - "jsesc": "~0.5.0" + "es6-error": "^4.0.1" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -6583,14 +9158,16 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, "requires": { "is-finite": "^1.0.0" } }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -6599,7 +9176,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -6609,7 +9186,7 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" } @@ -6617,24 +9194,22 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } }, "resolve-cwd": { @@ -6644,12 +9219,20 @@ "dev": true, "requires": { "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } } }, "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-url": { @@ -6668,53 +9251,32 @@ "signal-exit": "^3.0.2" } }, - "resumer": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", - "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", - "requires": { - "through": "~2.3.4" - } - }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "^7.0.5" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true }, - "rlp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz", - "integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==", + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "requires": { - "safe-buffer": "^5.1.1" + "glob": "^7.1.3" } }, "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true }, "run-queue": { "version": "1.0.3", @@ -6725,32 +9287,20 @@ "aproba": "^1.1.1" } }, - "rustbn.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==" - }, "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-event-emitter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz", - "integrity": "sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg==", - "requires": { - "events": "^3.0.0" - } + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true }, "safe-regex": { "version": "1.1.0", @@ -6764,198 +9314,46 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" - }, - "dependencies": { - "ajv": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", - "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "scrypt": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", - "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.0.8" - } - }, - "scrypt.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", - "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", - "dev": true, - "optional": true, - "requires": { - "scrypt": "^6.0.2", - "scryptsy": "^1.2.1" - } - }, - "scryptsy": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", - "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", - "dev": true, - "optional": true, - "requires": { - "pbkdf2": "^3.0.3" - } - }, - "secp256k1": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.2.tgz", - "integrity": "sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ==", - "requires": { - "bindings": "^1.2.1", - "bip66": "^1.1.3", - "bn.js": "^4.11.3", - "create-hash": "^1.1.2", - "drbg.js": "^1.0.1", - "elliptic": "^6.2.3", - "nan": "^2.2.1", - "safe-buffer": "^5.1.0" - } - }, - "seedrandom": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.4.tgz", - "integrity": "sha512-9A+PDmgm+2du77B5i0Ip2cxOqqHjgNxnBgglxLcX78A2D6c2rTo61z4jnVABpF4cKeDMDG+cmXXvdnqse2VqMA==" - }, - "seek-bzip": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", - "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", - "dev": true, - "optional": true, - "requires": { - "commander": "~2.8.1" - } - }, - "semaphore": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", - "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - } - } + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true }, - "serialize-javascript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "dev": true }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true }, - "servify": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", - "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", "dev": true, "requires": { - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "request": "^2.79.0", - "xhr": "^2.3.3" + "randombytes": "^2.1.0" } }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -6975,77 +9373,74 @@ } } }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "sha3": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", - "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, "requires": { - "nan": "2.10.0" + "kind-of": "^6.0.2" } }, "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" } }, "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shx": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.3.tgz", + "integrity": "sha512-nZJ3HFWVoTSyyB+evEKjJ1STiixGztlqwKLTUNV5KqMWtGey9fTd4KU1gdZ1X9BV6215pswQ/Jew9NsuS/fNDA==", + "dev": true, + "requires": { + "minimist": "^1.2.3", + "shelljs": "^0.8.4" + } + }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "simple-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true }, - "simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", - "dev": true, - "requires": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true }, "snapdragon": { "version": "0.8.2", @@ -7089,6 +9484,12 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -7163,52 +9564,59 @@ } } }, - "solc": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.24.tgz", - "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", "dev": true, "requires": { - "fs-extra": "^0.30.0", - "memorystream": "^0.3.1", - "require-from-string": "^1.1.0", - "semver": "^5.3.0", - "yargs": "^4.7.1" + "agent-base": "~4.2.1", + "socks": "~2.3.2" }, "dependencies": { - "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" + "es6-promisify": "^5.0.0" } } } }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -7216,9 +9624,9 @@ } }, "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -7239,33 +9647,77 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, + "spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "requires": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "spdx-correct": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", - "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", - "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==" + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } }, "split-string": { "version": "3.1.0", @@ -7276,10 +9728,26 @@ "extend-shallow": "^3.0.0" } }, + "split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dev": true, + "requires": { + "through2": "^2.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, "sshpk": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", - "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -7293,12 +9761,12 @@ } }, "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { - "safe-buffer": "^5.1.1" + "figgy-pudding": "^3.5.1" } }, "static-extend": { @@ -7322,22 +9790,6 @@ } } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, "stream-each": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", @@ -7348,97 +9800,66 @@ "stream-shift": "^1.0.0" } }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "stream-to-pull-stream": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/stream-to-pull-stream/-/stream-to-pull-stream-1.7.2.tgz", - "integrity": "sha1-dXYJrhzr0zx0MtSvvjH/eGULnd4=", - "requires": { - "looper": "^3.0.0", - "pull-stream": "^3.2.3" - }, - "dependencies": { - "looper": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz", - "integrity": "sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k=" - } - } - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } }, - "string.prototype.trim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", - "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.0", - "function-bind": "^1.0.2" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } }, "strip-ansi": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", - "dev": true, - "optional": true, - "requires": { - "is-natural-number": "^4.0.1" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true }, "strip-eof": { "version": "1.0.0", @@ -7446,146 +9867,111 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, "requires": { - "is-hex-prefixed": "1.0.0" + "min-indent": "^1.0.0" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "swarm-js": { - "version": "0.1.37", - "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.37.tgz", - "integrity": "sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ==", - "dev": true, - "optional": true, - "requires": { - "bluebird": "^3.5.0", - "buffer": "^5.0.5", - "decompress": "^4.0.0", - "eth-lib": "^0.1.26", - "fs-extra": "^2.1.2", - "fs-promise": "^2.0.0", - "got": "^7.1.0", - "mime-types": "^2.1.16", - "mkdirp-promise": "^5.0.1", - "mock-fs": "^4.1.0", - "setimmediate": "^1.0.5", - "tar.gz": "^1.0.5", - "xhr-request-promise": "^0.1.2" - } + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true }, - "tapable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", - "integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==", - "dev": true - }, - "tape": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz", - "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", - "requires": { - "deep-equal": "~1.0.1", - "defined": "~1.0.0", - "for-each": "~0.3.3", - "function-bind": "~1.1.1", - "glob": "~7.1.2", - "has": "~1.0.3", - "inherits": "~2.0.3", - "minimist": "~1.2.0", - "object-inspect": "~1.6.0", - "resolve": "~1.7.1", - "resumer": "~0.0.0", - "string.prototype.trim": "~1.1.2", - "through": "~2.3.8" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - } + "strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" } }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "optional": true, "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" + "has-flag": "^4.0.0" } }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "dev": true, "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" } }, - "tar.gz": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/tar.gz/-/tar.gz-1.0.7.tgz", - "integrity": "sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg==", + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, + "temp-write": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-3.4.0.tgz", + "integrity": "sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI=", "dev": true, - "optional": true, "requires": { - "bluebird": "^2.9.34", - "commander": "^2.8.1", - "fstream": "^1.0.8", - "mout": "^0.11.0", - "tar": "^2.1.1" + "graceful-fs": "^4.1.2", + "is-stream": "^1.1.0", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" }, "dependencies": { - "bluebird": { - "version": "2.11.0", - "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", - "dev": true, - "optional": true + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true } } }, - "temp": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", - "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "requires": { - "os-tmpdir": "^1.0.0", - "rimraf": "~2.2.6" - }, - "dependencies": { - "rimraf": { - "version": "2.2.8", - "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true - } + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" } }, + "text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true + }, "thenify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", - "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dev": true, "requires": { "any-promise": "^1.0.0" @@ -7602,57 +9988,69 @@ }, "through": { "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - } - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "setimmediate": "^1.0.4" - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } } }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": true - }, "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true }, "to-object-path": { "version": "0.3.0", @@ -7697,45 +10095,75 @@ } }, "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "^1.1.28", + "punycode": "^2.1.1" } }, - "treeify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", - "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==" + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "trim-newlines": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", + "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", + "dev": true }, - "trim-right": { + "trim-off-newlines": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", + "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", + "dev": true }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "ts-node": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, + "ts-transformer-inline-file": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ts-transformer-inline-file/-/ts-transformer-inline-file-0.1.1.tgz", + "integrity": "sha512-2bPkAFjATsRG4ld8TFTUqn4TvEdXLQf/wwGsepFeRKSXLPqFRhdUHusAGPB1/Zif3CVjppD+bfne58gynd8RfQ==", "dev": true }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", "dev": true }, + "ttypescript": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/ttypescript/-/ttypescript-1.5.12.tgz", + "integrity": "sha512-1ojRyJvpnmgN9kIHmUnQPlEV1gq+VVsxVYjk/NfvMlHSmYxjK5hEvOOU2MQASrbekTUiUM7pR/nXeCc8bzvMOQ==", + "dev": true, + "requires": { + "resolve": ">=1.9.0" + } + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -7743,181 +10171,65 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "requires": { "is-typedarray": "^1.0.0" } }, - "typewise": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", - "integrity": "sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE=", - "requires": { - "typewise-core": "^1.2.0" - } - }, - "typewise-core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", - "integrity": "sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU=" - }, - "typewiselite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typewiselite/-/typewiselite-1.0.0.tgz", - "integrity": "sha1-yIgvobsQksBgBal/NO9chQjjZk4=" - }, - "uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", - "dev": true, - "requires": { - "commander": "~2.13.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } + "typescript": { + "version": "4.1.1-rc", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.1-rc.tgz", + "integrity": "sha512-tgNcFrLIjlaMWEc7bKC0bxLNIt8BIAauY/HLUOQDyTP75HGskETtXOt46x4EKAHRKhWVLMc7yM02puTHa/yhCA==", + "dev": true }, - "uglifyjs-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "uglify-js": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.4.tgz", + "integrity": "sha512-kBFT3U4Dcj4/pJ52vfjCSfyLyvG9VYYuGYPmrPvAxRw/i7xHiT4VvCev+uiEMcEEiu6UNB6KgWmGtSUYIWScbw==", "dev": true, - "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "schema-utils": "^0.4.5", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "uglify-es": "^3.3.4", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } + "optional": true }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", "dev": true }, - "unbzip2-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz", - "integrity": "sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==", - "dev": true, - "optional": true, - "requires": { - "buffer": "^3.0.1", - "through": "^2.3.6" - }, - "dependencies": { - "base64-js": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", - "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", - "dev": true, - "optional": true - }, - "buffer": { - "version": "3.6.0", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", - "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", - "dev": true, - "optional": true, - "requires": { - "base64-js": "0.0.8", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - } - } - }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "umask": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz", + "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=", "dev": true }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "unique-filename": { @@ -7930,23 +10242,27 @@ } }, "unique-slug": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", - "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "dev": true, "requires": { "imurmurhash": "^0.1.4" } }, - "unorm": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.4.1.tgz", - "integrity": "sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA=" + "universal-user-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", + "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", + "dev": true, + "requires": { + "os-name": "^3.1.0" + } }, - "unpipe": { + "universalify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", "dev": true }, "unset-value": { @@ -7996,26 +10312,18 @@ } }, "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "dev": true, "requires": { "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - } } }, "urix": { @@ -8024,1033 +10332,446 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "url-set-query": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", - "dev": true - }, - "url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true, - "optional": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "util-promisify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", + "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3" + } }, - "v8-compile-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", - "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - } - }, - "web3": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.0.0-beta.35.tgz", - "integrity": "sha512-xwDmUhvTcHQvvNnOPcPZZgCxKUsI2e+GbHy7JkTK3/Rmnutazy8x7fsAXT9myw7V1qpi3GgLoZ3fkglSUbg1Mg==", - "dev": true, - "optional": true, - "requires": { - "web3-bzz": "1.0.0-beta.35", - "web3-core": "1.0.0-beta.35", - "web3-eth": "1.0.0-beta.35", - "web3-eth-personal": "1.0.0-beta.35", - "web3-net": "1.0.0-beta.35", - "web3-shh": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - } - }, - "web3-bzz": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.0.0-beta.35.tgz", - "integrity": "sha512-BhAU0qhlr8zltm4gs/+P1gki2VkxHJaM2Rrh4DGesDW0lzwufRoNvWFlwx1bKHoFPWNbSmm9PRkHOYOINL/Tgw==", - "dev": true, - "optional": true, - "requires": { - "got": "7.1.0", - "swarm-js": "0.1.37", - "underscore": "1.8.3" - } - }, - "web3-core": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.35.tgz", - "integrity": "sha512-ayGavbgVk4KL9Y88Uv411fBJ0SVgVfKhKEBweKYzmP0zOqneMzWt6YsyD1n6kRvjAbqA0AfUPEOKyMNjcx2tjw==", + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, "requires": { - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-core-requestmanager": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" + "defaults": "^1.0.3" } }, - "web3-core-helpers": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.35.tgz", - "integrity": "sha512-APOu3sEsamyqWt//8o4yq9KF25/uqGm+pQShson/sC4gKzmfJB07fLo2ond0X30E8fIqAPeVCotPXQxGciGUmA==", - "dev": true, - "requires": { - "underscore": "1.8.3", - "web3-eth-iban": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - } + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true }, - "web3-core-method": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.35.tgz", - "integrity": "sha512-jidImCide8q0GpfsO4L73qoHrbkeWgwU3uOH5DKtJtv0ccmG086knNMRgryb/o9ZgetDWLmDEsJnHjBSoIwcbA==", + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "dev": true, "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-promievent": "1.0.0-beta.35", - "web3-core-subscriptions": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" } }, - "web3-core-promievent": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.35.tgz", - "integrity": "sha512-GvqXqKq07OmHuVi5uNRg6k79a1/CI0ViCC+EtNv4CORHtDRmYEt5Bvdv6z6FJEiaaQkD0lKbFwNhLxutx7HItw==", + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { - "any-promise": "1.3.0", - "eventemitter3": "1.1.1" + "isexe": "^2.0.0" } }, - "web3-core-requestmanager": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.35.tgz", - "integrity": "sha512-S+zW2h17ZZQU9oe3yaCJE0E7aJS4C3Kf4kGPDv+nXjW0gKhQQhgVhw1Doq/aYQGqNSWJp7f1VHkz5gQWwg6RRg==", - "dev": true, - "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.35", - "web3-providers-http": "1.0.0-beta.35", - "web3-providers-ipc": "1.0.0-beta.35", - "web3-providers-ws": "1.0.0-beta.35" - } + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true }, - "web3-core-subscriptions": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.35.tgz", - "integrity": "sha512-gXzLrWvcGkGiWq1y33Z4Y80XI8XMrwowiQJkrPSjQ81K5PBKquOGwcMffLaKcwdmEy/NpsOXDeFo3eLE1Ghvvw==", - "dev": true, - "requires": { - "eventemitter3": "1.1.1", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.35" - } + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true }, - "web3-eth": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.0.0-beta.35.tgz", - "integrity": "sha512-04mcb2nGPXThawuuYICPOxv0xOHofvQKsjZeIq+89nyOC8DQMGTAErDkGyMHQYtjpth5XDhic0wuEsA80AmFZA==", + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, - "optional": true, "requires": { - "underscore": "1.8.3", - "web3-core": "1.0.0-beta.35", - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-core-subscriptions": "1.0.0-beta.35", - "web3-eth-abi": "1.0.0-beta.35", - "web3-eth-accounts": "1.0.0-beta.35", - "web3-eth-contract": "1.0.0-beta.35", - "web3-eth-iban": "1.0.0-beta.35", - "web3-eth-personal": "1.0.0-beta.35", - "web3-net": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" + "string-width": "^1.0.2 || 2" } }, - "web3-eth-abi": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.35.tgz", - "integrity": "sha512-KUDC+EtFFYG8z01ZleKrASdjj327/rtWHzEt6RWsEj7bBa0bGp9nEh+nqdZx/Sdgz1O8tnfFzJlrRcXpfr1vGg==", + "windows-release": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.3.tgz", + "integrity": "sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==", "dev": true, "requires": { - "bn.js": "4.11.6", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true - } + "execa": "^1.0.0" } }, - "web3-eth-accounts": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz", - "integrity": "sha512-duIgRsfht/0kAW/eQ0X9lKtVIykbETrnM2H7EnvplCzPHtQLodpib4o9JXfh9n6ZDgdDC7cuJoiVB9QJg089ew==", - "dev": true, - "optional": true, - "requires": { - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.7", - "scrypt.js": "0.2.0", - "underscore": "1.8.3", - "uuid": "2.0.1", - "web3-core": "1.0.0-beta.35", - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - }, - "dependencies": { - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "optional": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "uuid": { - "version": "2.0.1", - "resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true, - "optional": true - } - } + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true }, - "web3-eth-contract": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.35.tgz", - "integrity": "sha512-foPohOg5O1UCGKGZOIs+kQK5IZdV2QQ7pAWwNxH8WHplUA+fre1MurXNpoxknUmH6mYplFhXjqgYq2MsrBpHrA==", - "dev": true, - "optional": true, - "requires": { - "underscore": "1.8.3", - "web3-core": "1.0.0-beta.35", - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-core-promievent": "1.0.0-beta.35", - "web3-core-subscriptions": "1.0.0-beta.35", - "web3-eth-abi": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - } + "workerpool": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", + "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", + "dev": true }, - "web3-eth-iban": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.35.tgz", - "integrity": "sha512-H5wkcNcAIc+h/WoDIKv7ZYmrM2Xqu3O7jBQl1IWo73EDVQji+AoB2i3J8tuwI1yZRInRwrfpI3Zuwuf54hXHmQ==", + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { - "bn.js": "4.11.6", - "web3-utils": "1.0.0-beta.35" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true - } - } - }, - "web3-eth-personal": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.35.tgz", - "integrity": "sha512-AcM9nnlxu7ZRRxPvkrFB9eLxMM4A2cPfj2aCg21Wb2EpMnhR+b/O1cT33k7ApRowoMpM+T9M8vx2oPNwXfaCOQ==", - "dev": true, - "requires": { - "web3-core": "1.0.0-beta.35", - "web3-core-helpers": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-net": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - } - }, - "web3-net": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.0.0-beta.35.tgz", - "integrity": "sha512-bbwaQ/KohGjIJ6HAKbZ6KrklCAaG6/B7hIbAbVLSFLxF+Yz9lmAgQYaDInpidpC/NLb3WOmcbRF+P77J4qMVIA==", - "dev": true, - "requires": { - "web3-core": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-utils": "1.0.0-beta.35" - } - }, - "web3-provider-engine": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-14.1.0.tgz", - "integrity": "sha512-vGZtqhSUzGTiMGhJXNnB/aRDlrPZLhLnBZ2NPArkZtr8XSrwg9m08tw4+PuWg5za0TJuoE/vuPQc501HddZZWw==", - "requires": { - "async": "^2.5.0", - "backoff": "^2.5.0", - "clone": "^2.0.0", - "cross-fetch": "^2.1.0", - "eth-block-tracker": "^3.0.0", - "eth-json-rpc-infura": "^3.1.0", - "eth-sig-util": "^1.4.2", - "ethereumjs-block": "^1.2.2", - "ethereumjs-tx": "^1.2.0", - "ethereumjs-util": "^5.1.5", - "ethereumjs-vm": "^2.3.4", - "json-rpc-error": "^2.0.0", - "json-stable-stringify": "^1.0.1", - "promise-to-callback": "^1.0.0", - "readable-stream": "^2.2.9", - "request": "^2.85.0", - "semaphore": "^1.0.3", - "ws": "^5.1.1", - "xhr": "^2.2.0", - "xtend": "^4.0.1" - }, - "dependencies": { - "eth-sig-util": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", - "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", - "requires": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", - "ethereumjs-util": "^5.1.1" - } }, - "ethereumjs-abi": { - "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", - "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", - "requires": { - "bn.js": "^4.10.0", - "ethereumjs-util": "^5.0.0" - } - }, - "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "web3-providers-http": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.35.tgz", - "integrity": "sha512-DcIMFq52Fb08UpWyZ3ZlES6NsNqJnco4hBS/Ej6eOcASfuUayPI+GLkYVZsnF3cBYqlH+DOKuArcKSuIxK7jIA==", - "dev": true, - "requires": { - "web3-core-helpers": "1.0.0-beta.35", - "xhr2-cookies": "1.1.0" - } - }, - "web3-providers-ipc": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.35.tgz", - "integrity": "sha512-iB0FG0HcpUnayfa8pn4guqEQ4Y1nrroi/jffdtQgFkrNt0sD3fMSwwC0AbmECqj3tDLl0e1slBR0RENll+ZF0g==", - "dev": true, - "requires": { - "oboe": "2.1.3", - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.35" - } - }, - "web3-providers-ws": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.35.tgz", - "integrity": "sha512-Cx64NgDStynKaUGDIIOfaCd0fZusL8h5avKTkdTjUu2aHhFJhZoVBGVLhoDtUaqZGWIZGcBJOoVf2JkGUOjDRQ==", - "dev": true, - "requires": { - "underscore": "1.8.3", - "web3-core-helpers": "1.0.0-beta.35", - "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "ms": "2.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, - "websocket": { - "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", - "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "debug": "^2.2.0", - "nan": "^2.3.3", - "typedarray-to-buffer": "^3.1.2", - "yaeti": "^0.0.6" + "ansi-regex": "^4.1.0" } } } }, - "web3-shh": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.0.0-beta.35.tgz", - "integrity": "sha512-8qSonk/x0xabERS9Sr6AIADN/Ty+5KwARkkGIfSYHKqFpdMDz+76F7cUCxtoCZoS8K04xgZlDKYe0TJXLYA0Fw==", + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "dev": true, - "optional": true, "requires": { - "web3-core": "1.0.0-beta.35", - "web3-core-method": "1.0.0-beta.35", - "web3-core-subscriptions": "1.0.0-beta.35", - "web3-net": "1.0.0-beta.35" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, - "web3-utils": { - "version": "1.0.0-beta.35", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.35.tgz", - "integrity": "sha512-Dq6f0SOKj3BDFRgOPnE6ALbzBDCKVIW8mKWVf7tGVhTDHf+wQaWwQSC3aArFSqdExB75BPBPyDpuMTNszhljpA==", + "write-json-file": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", + "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", "dev": true, "requires": { - "bn.js": "4.11.6", - "eth-lib": "0.1.27", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randomhex": "0.1.5", - "underscore": "1.8.3", - "utf8": "2.1.1" + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.15", + "make-dir": "^2.1.0", + "pify": "^4.0.1", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.4.2" }, "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true - }, - "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=", - "dev": true - } - } - }, - "webpack": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.17.1.tgz", - "integrity": "sha512-vdPYogljzWPhFKDj3Gcp01Vqgu7K3IQlybc3XIdKSQHelK1C3eIQuysEUR7MxKJmdandZlQB/9BG2Jb1leJHaw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-module-context": "1.5.13", - "@webassemblyjs/wasm-edit": "1.5.13", - "@webassemblyjs/wasm-opt": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", - "acorn": "^5.6.2", - "acorn-dynamic-import": "^3.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^0.4.4", - "tapable": "^1.0.0", - "uglifyjs-webpack-plugin": "^1.2.4", - "watchpack": "^1.5.0", - "webpack-sources": "^1.0.1" - }, - "dependencies": { - "ajv": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", - "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } }, - "webpack-bundle-size-analyzer": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-size-analyzer/-/webpack-bundle-size-analyzer-2.7.0.tgz", - "integrity": "sha1-LsBTn9V/hxYIOJizi4kv6UyIxrw=", - "dev": true, - "requires": { - "commander": "^2.7.1", - "filesize": "^3.1.2", - "humanize": "0.0.9" - } - }, - "webpack-cli": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.0.tgz", - "integrity": "sha512-p5NeKDtYwjZozUWq6kGNs9w+Gtw/CPvyuXjXn2HMdz8Tie+krjEg8oAtonvIyITZdvpF7XG9xDHwscLr2c+ugQ==", + "write-pkg": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-3.2.0.tgz", + "integrity": "sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==", "dev": true, "requires": { - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.0.0", - "global-modules-path": "^2.1.0", - "import-local": "^1.0.0", - "inquirer": "^6.0.0", - "interpret": "^1.1.0", - "loader-utils": "^1.1.0", - "supports-color": "^5.4.0", - "v8-compile-cache": "^2.0.0", - "yargs": "^12.0.1" + "sort-keys": "^2.0.0", + "write-json-file": "^2.2.0" }, "dependencies": { - "ansi-regex": { + "pify": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "write-json-file": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz", + "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=", "dev": true, "requires": { - "color-convert": "^1.9.0" + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.0.0" } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + } + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true + }, + "yargs": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz", + "integrity": "sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.2", + "yargs-parser": "^20.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "color-convert": "^2.0.1" } }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz", + "integrity": "sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==", "dev": true, "requires": { - "xregexp": "4.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "color-name": "~1.1.4" } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", - "dev": true, - "requires": { - "execa": "^0.10.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "path-exists": { + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "y18n": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.4.tgz", + "integrity": "sha512-deLOfD+RvFgrpAmSZgfGdWYE+OKyHcVHaRQ7NphG/63scpRvTHHeQMAxGGvaLVGJ+HYVcCXlzcTK0ZehFf+eHQ==", "dev": true }, - "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^2.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" - } - }, "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } + "version": "20.2.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz", + "integrity": "sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww==", + "dev": true } } }, - "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "yargs-parser": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", "dev": true, "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true } } }, - "websocket": { - "version": "1.0.26", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.26.tgz", - "integrity": "sha512-fjcrYDPIQxpTnqFQ9JjxUQcdvR89MFAOjPBlF+vjOt49w/XW4fJknUoMz/mDIn2eK1AdslVojcaOxOqyZZV8rw==", - "requires": { - "debug": "^2.2.0", - "nan": "^2.3.3", - "typedarray-to-buffer": "^3.1.2", - "yaeti": "^0.0.6" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "whatwg-fetch": { - "version": "2.0.4", - "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" - }, - "worker-farm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "xhr": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", - "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", - "requires": { - "global": "~4.3.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { - "buffer-to-arraybuffer": "^0.0.5", - "object-assign": "^4.1.1", - "query-string": "^5.0.1", - "simple-get": "^2.7.0", - "timed-out": "^4.0.1", - "url-set-query": "^1.0.0", - "xhr": "^2.0.4" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true } } }, - "xhr-request-promise": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz", - "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", - "dev": true, - "requires": { - "xhr-request": "^1.0.1" - } - }, - "xhr2-cookies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", - "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", - "dev": true, - "requires": { - "cookiejar": "^2.1.1" - } - }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true - }, - "yargs": { - "version": "4.8.1", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "requires": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "lodash.assign": "^4.0.3", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.1", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.1" - } - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "requires": { - "camelcase": "^3.0.0", - "lodash.assign": "^4.0.6" - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "optional": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } } } } diff --git a/package.json b/package.json index da5dd55e9c..01d6bb00ae 100644 --- a/package.json +++ b/package.json @@ -1,74 +1,58 @@ { - "name": "ganache-core", - "version": "2.2.1", - "main": "./index.js", + "name": "root", + "author": "David Murdoch (https://davidmurdoch.com)", + "private": true, "engines": { - "node": ">=8.9.0" - }, - "directories": { - "lib": "./lib" + "node": ">=10.7.0 <=14.14.0", + "npm": ">=6.1.0" }, "scripts": { - "build": "npm run build-core", - "build-core": "webpack-cli --config ./webpack/node/core.webpack.config.js", - "build-provider": "webpack-cli --config ./webpack/node/provider.webpack.config.js", - "build-server": "webpack-cli --config ./webpack/node/server.webpack.config.js", - "build-web": "webpack-cli --config ./webpack/web-experimental/core.webpack.config.js && webpack-cli --config ./webpack/web-experimental/server.webpack.config.js && webpack-cli --config ./webpack/web-experimental/provider.webpack.config.js", - "prepublishOnly": "npm run test && npm run build && npm run test-build", - "test": "mocha --check-leaks --recursive --globals _scratch,sanitizedData", - "test-build": "cross-env TEST_BUILD=node mocha --check-leaks --recursive --globals _scratch,sanitizedData", - "test-web-experimental": "cross-env TEST_BUILD=web-experimental mocha --check-leaks --recursive --globals _scratch,sanitizedData" - }, - "dependencies": { - "abstract-leveldown": "3.0.0", - "async": "2.6.1", - "bip39": "2.5.0", - "bn.js": "4.11.8", - "cachedown": "1.0.0", - "clone": "2.1.2", - "debug": "3.1.0", - "encoding-down": "5.0.4", - "eth-sig-util": "2.0.2", - "ethereumjs-abi": "0.6.5", - "ethereumjs-account": "2.0.5", - "ethereumjs-block": "1.2.2", - "ethereumjs-tx": "1.3.4", - "ethereumjs-util": "5.2.0", - "ethereumjs-vm": "2.4.0", - "heap": "0.2.6", - "intercept-require": "^1.1.0", - "level-sublevel": "6.6.4", - "levelup": "3.1.1", - "lodash": "4.17.10", - "merkle-patricia-tree": "2.3.1", - "seedrandom": "2.4.4", - "tmp": "0.0.33", - "web3-provider-engine": "^14.0.6", - "websocket": "1.0.26" + "build": "lerna run build", + "clean": "npx shx rm -rf node_modules && npx lerna clean -y && npm run tsc.clean", + "create": "ts-node ./scripts/create", + "docs.build": "lerna run docs.build", + "docs.preview": "lerna run docs.preview", + "postinstall": "lerna bootstrap && ts-node ./scripts/postinstall", + "reinstall": "npm run clean && npm install", + "test": "lerna exec -- npm run test", + "tsc": "lerna exec -- npm run tsc", + "tsc.clean": "npx lerna exec -- npx shx rm -rf lib dist" }, "devDependencies": { - "ethereumjs-wallet": "0.6.2", - "assert-match": "1.1.1", - "browserfs": "1.4.3", - "cross-env": "5.2.0", - "memdown": "1.3.1", - "mocha": "5.2.0", - "pify": "4.0.0", - "solc": "0.4.24", - "source-map-support": "^0.5.9", - "temp": "0.8.3", - "webpack": "4.17.1", - "webpack-bundle-size-analyzer": "2.7.0", - "webpack-cli": "3.1.0", - "web3": "1.0.0-beta.35" - }, - "optionalDependencies": { - "ethereumjs-wallet": "0.6.2", - "web3": "1.0.0-beta.35" - }, - "repository": { - "type": "git", - "url": "https://github.com/trufflesuite/ganache-core" + "@istanbuljs/nyc-config-typescript": "1.0.1", + "@types/fs-extra": "9.0.2", + "@types/mocha": "8.0.3", + "@types/node": "14.14.6", + "@types/npm-package-arg": "6.1.0", + "@types/prettier": "2.1.5", + "@types/yargs": "15.0.9", + "@zerollup/ts-transform-paths": "1.7.18", + "camelcase": "6.1.0", + "chalk": "4.1.0", + "cli-highlight": "2.1.4", + "cross-env": "7.0.2", + "fs-extra": "9.0.1", + "git-user-name": "2.0.0", + "husky": "4.3.0", + "into-stream": "6.0.0", + "lerna": "3.22.1", + "mocha": "8.2.0", + "monaco-editor": "0.21.2", + "npm-package-arg": "8.1.0", + "nyc": "15.1.0", + "prettier": "2.1.2", + "pretty-quick": "3.1.0", + "shx": "0.3.3", + "ts-node": "9.0.0", + "ts-transformer-inline-file": "0.1.1", + "ttypescript": "1.5.12", + "typescript": "4.1.1-rc", + "yargs": "16.1.0" }, - "license": "MIT" + "license": "MIT", + "husky": { + "hooks": { + "pre-commit": "pretty-quick --staged" + } + } } diff --git a/perf/transactions.js b/perf/transactions.js deleted file mode 100755 index 7d6096e259..0000000000 --- a/perf/transactions.js +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env node -var TestRPC = require("../"); -var Web3 = require("web3"); -var async = require("async") - -var server = TestRPC.server(); -var port = 12345; -var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:" + port)); - -function runTest(times, fn, callback) { - var start = new Date(); - - async.timesSeries(times, fn, function(err) { - if (err) return callback(err); - - var end = new Date(); - var actualTime = end.getTime() - start.getTime(); - - callback(null, actualTime); - }); -} - -function runAverage(title, number_of_runs, fn_times, fn, callback) { - var results = new Array(number_of_runs); - - async.timesSeries(number_of_runs, function(n, next) { - process.stdout.write(title + " " + (n + 1) + "..."); - - runTest(fn_times, fn, function(err, totalTime) { - if (err) return next(err); - results[n] = totalTime; - - console.log((totalTime / 1000) + " seconds"); - next(); - }); - }, function(err) { - if (err) return callback(err); - - var sum = results.reduce(function(a, b) { - return a + b; - }, 0); - - var average = sum / number_of_runs; - - console.log("Average " + (average / 1000) + " seconds"); - - callback(null, average); - }); -}; - -function bailIfError(err) { - if (err) { - console.log(err); - process.exit(1); - } -} - -server.listen(port, function(err) { - bailIfError(err); - - web3.eth.getAccounts(function(err, accounts) { - bailIfError(err); - - runAverage("Running transactions test", 4, 1000, function(n, cb) { - web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: 500, // wei - gas: 90000 - }, cb); - }, function(err) { - bailIfError(err); - server.close(); - }); - }); -}); diff --git a/public-exports.js b/public-exports.js deleted file mode 100644 index 8fad25264d..0000000000 --- a/public-exports.js +++ /dev/null @@ -1,16 +0,0 @@ -// make sourcemaps work! -require('source-map-support/register'); - -const Provider = require("./lib/provider"); -const Server = require("./lib/server"); - -// This interface exists so as not to cause breaking changes. -module.exports = { - server: function(options) { - return Server.create(options); - }, - provider: function(options) { - return new Provider(options); - }, - _webpacked: true -}; \ No newline at end of file diff --git a/scripts/create.ts b/scripts/create.ts new file mode 100644 index 0000000000..aab83848c2 --- /dev/null +++ b/scripts/create.ts @@ -0,0 +1,279 @@ +// TODO: make this its own package? + +import chalk from "chalk"; +import yargs from "yargs"; +import prettier from "prettier"; +import camelCase from "camelcase"; +import npa from "npm-package-arg"; +import userName from "git-user-name"; +import { join, resolve } from "path"; +import { highlight } from "cli-highlight"; +import { mkdir, mkdirSync, writeFile } from "fs-extra"; +import { + lstatSync as lstat, + readdirSync as readDir, + readFileSync as readFile +} from "fs"; + +const isDir = (s: string) => lstat(s).isDirectory(); +const getDirectories = (s: string) => readDir(s).filter(n => isDir(join(s, n))); + +const COLORS = { + Bold: "\x1b[1m", + Reset: "\x1b[0m", + FgRed: "\x1b[31m" +}; + +const scopes = getDirectories(join(__dirname, "../src")); +const argv = yargs + .command( + `$0 --location`, + `Create a new package in the given location with the provided name.`, + yargs => { + return yargs + .usage( + chalk`{hex("#e4a663").bold Create a new package in the given location with the provided name.}\n\n` + + chalk`{bold Usage}\n {bold $} {dim <}name{dim >} {dim --}location {dim <}${scopes.join( + chalk.dim(" | ") + )}{dim >}` + ) + .positional("", { + describe: ` The name of the new package`, + type: "string", + demandOption: true + }) + .alias("name", "") + .option("location", { + alias: "l", + default: "packages", + describe: `The location for the new package.`, + choices: scopes, + type: "string", + demandOption: true + }); + } + ) + .demandCommand() + .version(false) + .help(false) + .updateStrings({ + "Positionals:": chalk.bold("Options"), + "Options:": ` `, + "Not enough non-option arguments: got %s, need at least %s": { + one: chalk`{red {bold ERROR! Not enough non-option arguments:}\n got %s, need at least %s}`, + other: chalk`{red {bold ERROR! Not enough non-option arguments:}\n got %s, need at least %s}` + } as any, + "Invalid values:": `${COLORS.FgRed}${COLORS.Bold}ERROR! Invalid values:${COLORS.Reset}${COLORS.FgRed}` + }) + .fail((msg, err, yargs) => { + // we use a custom `fail` fn so that NPM doesn't print its own giant error message. + if (err) throw err; + + console.error(yargs.help().toString().replace("\n\n\n", "\n")); + console.error(); + console.error(msg); + process.exit(0); + }).argv; +process.stdout.write(`${COLORS.Reset}`); + +(async function () { + let name = argv.name; + let location = argv.location; + + try { + const workspaceDir = join(__dirname, "../"); + const LICENSE = readFile(join(workspaceDir, "LICENSE"), "utf-8"); + + const prettierConfig = await prettier.resolveConfig(process.cwd()); + + name = npa(name).name; + + const packageName = `@ganache/${name}`; + let packageAuthor = userName(); + const version = "0.1.0"; + + const pkg = { + name: packageName, + version, + description: "", + author: packageAuthor || require("../package.json").author, + homepage: `https://github.com/trufflesuite/ganache-core/tree/develop/src/${location}/${name}#readme`, + license: "MIT", + main: "lib/index.js", + types: "src/index.ts", + source: "index.ts", + directories: { + lib: "lib", + test: "test" + }, + files: ["lib"], + repository: { + type: "git", + url: "https://github.com/trufflesuite/ganache-core.git", + directory: `src/${location}/${name}` + }, + scripts: { + tsc: "ttsc", + test: "nyc npm run mocha", + mocha: + "cross-env TS_NODE_COMPILER=ttypescript TS_NODE_FILES=true mocha --exit --check-leaks --throw-deprecation --trace-warnings --require ts-node/register 'tests/**/*.test.ts'" + }, + bugs: { + url: "https://github.com/trufflesuite/ganache-core/issues" + }, + keywords: [ + "ganache", + `ganache-${name}`, + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling", + "truffle" + ] + }; + + const tsConfig = { + extends: "../../../tsconfig.json", + compilerOptions: { + outDir: "lib" + }, + include: ["src"] + }; + + const shrinkwrap = { + name: packageName, + version: version, + lockfileVersion: 1 + }; + + const testFile = `import assert from "assert"; +import ${camelCase(name)} from "../src/"; + +describe("${packageName}", () => { + it("needs tests"); +})`; + + const indexFile = `export default { + // TODO +} +`; + + const dir = join(workspaceDir, "src", location, name); + const tests = join(dir, "tests"); + const src = join(dir, "src"); + + function initSrc() { + return writeFile( + join(src, "index.ts"), + prettier.format(indexFile, { ...prettierConfig, parser: "typescript" }) + ); + } + + function initIndex() { + // When a bundler compiles our libs this headerdoc comment will cause that + // tool to retain our LICENSE information in their bundled output. + const headerdoc = `/*! + * ${packageName} + * + * @copyright Truffle Blockchain Group + * @author ${pkg.author} + * @license ${pkg.license} +*/ + +`; + return writeFile( + join(dir, "index.ts"), + prettier.format(headerdoc + indexFile, { + ...prettierConfig, + parser: "typescript" + }) + ); + } + + function initRootFiles() { + return Promise.all([ + writeFile( + join(dir, ".npmignore"), + `./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json +` + ), + writeFile(join(dir, "LICENSE"), LICENSE) + ]); + } + + function initTests() { + return writeFile( + join(tests, "index.test.ts"), + prettier.format(testFile, { ...prettierConfig, parser: "typescript" }) + ); + } + + const pkgStr = JSON.stringify(pkg, null, 2) + "\n"; + const pkgPath = join(dir, "package.json"); + + console.log(`About to write to ${resolve(__dirname, pkgPath)}`); + console.log(""); + + mkdirSync(dir); + + await Promise.all([ + initRootFiles(), + initIndex(), + mkdir(tests).then(initTests), + mkdir(src).then(initSrc), + writeFile( + join(dir, "tsconfig.json"), + JSON.stringify(tsConfig, null, 2) + "\n" + ), + writeFile( + join(dir, "README.md"), + prettier.format(`# \`${packageName}\`\n> TODO: description`, { + ...prettierConfig, + parser: "markdown" + }) + ), + writeFile(pkgPath, pkgStr), + writeFile( + join(dir, "npm-shrinkwrap.json"), + JSON.stringify(shrinkwrap) + "\n" + ) + ]); + + console.log( + highlight(pkgStr, { + language: "json", + theme: { + attr: chalk.hex("#3FE0C5"), + string: chalk.hex("#e4a663") + } + }) + ); + + console.log( + chalk`{green success} {magenta create} New package {bgBlack ${name} } created at ./src/packages/${name}.` + ); + console.log(""); + console.log( + chalk` Update the package.json here: {bold ${dir}/package.json}` + ); + } catch (e) { + console.error(e); + console.log(""); + console.log( + chalk`{red fail} {magenta create} New package {bgBlack ${name} } not created. See error above.` + ); + } +})(); diff --git a/scripts/postinstall.ts b/scripts/postinstall.ts new file mode 100644 index 0000000000..bf6bb8e904 --- /dev/null +++ b/scripts/postinstall.ts @@ -0,0 +1,7 @@ +import chalk from "chalk"; + +console.log(""); +console.log( + chalk`{bold.cyan Tip:} {cyan run} {bold.yellow.dim source completions.sh} {cyan to supply bash completions for npm scripts}` +); +console.log(""); diff --git a/src/chains/ethereum/.npmignore b/src/chains/ethereum/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/chains/ethereum/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/chains/ethereum/LICENSE b/src/chains/ethereum/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/chains/ethereum/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/chains/ethereum/README.md b/src/chains/ethereum/README.md new file mode 100644 index 0000000000..7a449f8f46 --- /dev/null +++ b/src/chains/ethereum/README.md @@ -0,0 +1,3 @@ +# `@ganache/ethereum` + +This is ganache's Ethereum client implementation. diff --git a/src/chains/ethereum/index.ts b/src/chains/ethereum/index.ts new file mode 100644 index 0000000000..e035a1fa9f --- /dev/null +++ b/src/chains/ethereum/index.ts @@ -0,0 +1,9 @@ +/*! + * @ganache/ethereum + * + * @copyright 2019-2020 Truffle Blockchain Group + * @author David Murdoch (https://davidmurdoch.com) + * @license MIT + */ + +export * from "./src/connector"; diff --git a/src/chains/ethereum/npm-shrinkwrap.json b/src/chains/ethereum/npm-shrinkwrap.json new file mode 100644 index 0000000000..9e70451782 --- /dev/null +++ b/src/chains/ethereum/npm-shrinkwrap.json @@ -0,0 +1,3919 @@ +{ + "name": "@ganache/ethereum", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@koa/cors": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@koa/cors/-/cors-3.1.0.tgz", + "integrity": "sha512-7ulRC1da/rBa6kj6P4g2aJfnET3z8Uf3SWu60cjbtxTA5g8lxRdX/Bd2P92EagGwwAhANeNw8T8if99rJliR6Q==", + "dev": true, + "requires": { + "vary": "^1.1.2" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@trufflesuite/typedoc-default-themes": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@trufflesuite/typedoc-default-themes/-/typedoc-default-themes-0.6.1.tgz", + "integrity": "sha512-/wt3Jp+fD/DsxArEMixt94hDjHlB6R82Xa2ffjoCzlXrF8OSidzmzYkMvuxi53t1PaQvobNY5wMTXUqGnt/HXA==", + "dev": true, + "requires": { + "backbone": "^1.4.0", + "jquery": "^3.4.1", + "lunr": "^2.3.6", + "underscore": "^1.9.1" + } + }, + "@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "requires": { + "@types/node": "*" + } + }, + "@types/fs-extra": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.2.tgz", + "integrity": "sha512-jp0RI6xfZpi5JL8v7WQwpBEQTq63RqW2kxwTZt+m27LcJqQdPVU1yGnT1ZI4EtCDynQQJtIGyQahkiCGCS7e+A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-/MxAVmtyyeOvZ6dGf3ciLwFRuV5M8DRIyYNFGHYI6UyBW4/XqyO0LZw+JFMvaeY3cHItQAkELclBU1x5ank6mg==", + "requires": { + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.14.164", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.164.tgz", + "integrity": "sha512-fXCEmONnrtbYUc5014avwBeMdhHHO8YJCkOBflUL9EoJBSKZ1dei+VO74fA7JkTHZ1GvZack2TyIw5U+1lT8jg==", + "dev": true + }, + "@types/lodash.clonedeep": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.6.tgz", + "integrity": "sha512-cE1jYr2dEg1wBImvXlNtp0xDoS79rfEdGozQVgliDZj1uERH4k+rmEMTudP9b4VQ8O6nRb5gPqft0QzEQGMQgA==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/node": { + "version": "14.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.23.tgz", + "integrity": "sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw==" + }, + "@types/pbkdf2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/secp256k1": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", + "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "requires": { + "@types/node": "*" + } + }, + "@types/seedrandom": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.28.tgz", + "integrity": "sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA==", + "dev": true + }, + "@types/ws": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.2.7.tgz", + "integrity": "sha512-UUFC/xxqFLP17hTva8/lVT0SybLUrfSD9c+iapKb0fEiC8uoDbA+xuZ3pAN603eW+bY8ebSMLm9jXdIPnD0ZgA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "requires": { + "xtend": "~4.0.0" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "agent-base": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "ansi-escape-sequences": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-5.1.2.tgz", + "integrity": "sha512-JcpoVp1W1bl1Qn4cVuiXEhD6+dyXKSOgCn2zlzE8inYgCJCBy1aPnUhlz6I4DFum8D4ovb9Qi/iAjUcGvG2lqw==", + "dev": true, + "requires": { + "array-back": "^4.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, + "array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-eventemitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", + "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", + "requires": { + "async": "^2.4.0" + } + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, + "backbone": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz", + "integrity": "sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ==", + "dev": true, + "requires": { + "underscore": ">=1.8.3" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base-x": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bip39": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz", + "integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==", + "requires": { + "@types/node": "11.11.6", + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1" + }, + "dependencies": { + "@types/node": { + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" + } + } + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" + }, + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "byte-size": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-6.2.0.tgz", + "integrity": "sha512-6EspYUCAPMc7E2rltBgKwhG+Cmk0pDm9zDtF1Awe2dczNUL3YpZ8mTs/dueOTS1hqGWBOatqef4jYMGjln7WmA==", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "dev": true, + "requires": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "checkpoint-store": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", + "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", + "requires": { + "functional-red-black-tree": "^1.0.1" + } + }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "co-body": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.0.0.tgz", + "integrity": "sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw==", + "dev": true, + "requires": { + "inflation": "^2.0.0", + "qs": "^6.5.2", + "raw-body": "^2.3.3", + "type-is": "^1.6.16" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "dev": true + }, + "command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "dev": true, + "requires": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true + } + } + }, + "command-line-usage": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", + "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "chalk": "^2.4.2", + "table-layout": "^1.0.0", + "typical": "^5.2.0" + }, + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "common-log-format": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/common-log-format/-/common-log-format-1.0.0.tgz", + "integrity": "sha512-fFn/WPNbsTCGTTwdCpZfVZSa5mgqMEkA0gMTRApFSlEsYN+9B2FPfiqch5FT+jsv5IV1RHV3GeZvCa7Qg+jssw==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "dev": true, + "requires": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + } + } + }, + "copy-to": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", + "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=", + "dev": true + }, + "core-js-pure": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", + "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "create-mixin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/create-mixin/-/create-mixin-3.0.0.tgz", + "integrity": "sha512-LkdMqnWT9LaqBN4huqpUnMz56Yr1mVSoCduAd2xXefgH/YZP2sXCMAyztXjk4q8hTF/TlcDa+zQW2aTgGdjjKQ==", + "dev": true + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "requires": { + "abstract-leveldown": "~2.6.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + } + } + }, + "defined": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emittery": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", + "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "requires": { + "abstract-leveldown": "^5.0.0", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "~4.0.0" + } + }, + "level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "requires": { + "buffer": "^5.6.0" + } + }, + "level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "requires": { + "errno": "~0.1.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eth-sig-util": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.5.3.tgz", + "integrity": "sha512-KpXbCKmmBUNUTGh9MRKmNkIPietfhzBqqYqysDavLseIiMUGl95k6UcPEkALAZlj41e9E6yioYXc1PC333RKqw==", + "requires": { + "buffer": "^5.2.1", + "elliptic": "^6.4.0", + "ethereumjs-abi": "0.6.5", + "ethereumjs-util": "^5.1.1", + "tweetnacl": "^1.0.0", + "tweetnacl-util": "^0.15.0" + }, + "dependencies": { + "ethereumjs-abi": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", + "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", + "requires": { + "bn.js": "^4.10.0", + "ethereumjs-util": "^4.3.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz", + "integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==", + "requires": { + "bn.js": "^4.8.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.0.0" + } + } + } + }, + "ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + } + } + }, + "ethashjs": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz", + "integrity": "sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==", + "requires": { + "async": "^2.1.2", + "buffer-xor": "^2.0.1", + "ethereumjs-util": "^7.0.2", + "miller-rabin": "^4.0.0" + }, + "dependencies": { + "bn.js": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", + "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==" + }, + "buffer-xor": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", + "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "ethereumjs-util": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.3.tgz", + "integrity": "sha512-uLQsGPOwsRxe50WV1Dybh5N8zXDz4ev7wP49LKX9kr28I5TmcDILPgpKK/BFe5zYSfRGEeo+hPT7W3tjghYLuA==", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + } + } + }, + "ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "requires": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "requires": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + } + } + }, + "ethereumjs-account": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz", + "integrity": "sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA==", + "requires": { + "ethereumjs-util": "^6.0.0", + "rlp": "^2.2.1", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + } + } + }, + "ethereumjs-block": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", + "requires": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "requires": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "requires": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "ethereumjs-blockchain": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.3.tgz", + "integrity": "sha512-0nJWbyA+Gu0ZKZr/cywMtB/77aS/4lOVsIKbgUN2sFQYscXO5rPbUfrEe7G2Zhjp86/a0VqLllemDSTHvx3vZA==", + "requires": { + "async": "^2.6.1", + "ethashjs": "~0.0.7", + "ethereumjs-block": "~2.2.2", + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "~6.1.0", + "flow-stoplight": "^1.0.0", + "level-mem": "^3.0.1", + "lru-cache": "^5.1.1", + "rlp": "^2.2.2", + "semaphore": "^1.1.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, + "secp256k1": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", + "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", + "requires": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.5.2", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + } + } + } + }, + "ethereumjs-common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", + "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==" + }, + "ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "requires": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + } + } + }, + "ethereumjs-util": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.7.tgz", + "integrity": "sha512-vU5rtZBlZsgkTw3o6PDKyB8li2EgLavnAbsKcfsH2YhHH1Le+PP8vEiMnAnvgc1B6uMoaM5GDCrVztBw0Q5K9g==", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + }, + "dependencies": { + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + } + } + }, + "ethereumjs-vm": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz", + "integrity": "sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA==", + "requires": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "core-js-pure": "^3.0.1", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.2", + "ethereumjs-blockchain": "^4.0.3", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.2", + "ethereumjs-util": "^6.2.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.3.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1", + "util.promisify": "^1.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "requires": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + } + }, + "merkle-patricia-tree": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", + "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", + "requires": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "fake-merkle-patricia-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", + "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", + "requires": { + "checkpoint-store": "^1.1.0" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + } + } + }, + "flow-stoplight": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz", + "integrity": "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=" + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hdkey": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-2.0.1.tgz", + "integrity": "sha512-c+tl9PHG9/XkGgG0tD7CJpRVaE0jfZizDNmnErUAKQ4EjQSOcOUcV3EN9ZEZS8pZ4usaeiiK0H7stzuzna8feA==", + "requires": { + "bs58check": "^2.1.2", + "safe-buffer": "^5.1.1", + "secp256k1": "^4.0.0" + } + }, + "highlight.js": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.1.2.tgz", + "integrity": "sha512-Q39v/Mn5mfBlMff9r+zzA+gWxRsCRKwEMvYTiisLr/XUiFI/4puWt0Ojdko3R3JCNWGdOWaA5g/Yxqa23kC5AA==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "http-assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", + "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "http-errors": "~1.7.2" + }, + "dependencies": { + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + } + } + }, + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + } + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==" + }, + "inflation": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", + "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + }, + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", + "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "dev": true + }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "jquery": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", + "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==", + "dev": true + }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "keccak": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.0.tgz", + "integrity": "sha512-/4h4FIfFEpTEuySXi/nVFM5rqSKPnnhI7cL4K3MFSwoI3VyM7AhPSq3SsysARtnEBEeIKMBUWD8cTh9nHE8AkA==", + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dev": true, + "requires": { + "tsscmp": "1.0.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "koa": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.0.tgz", + "integrity": "sha512-i/XJVOfPw7npbMv67+bOeXr3gPqOAw6uh5wFyNs3QvJ47tUx3M3V9rIE0//WytY42MKz4l/MXKyGkQ2LQTfLUQ==", + "dev": true, + "requires": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "~3.1.0", + "delegates": "^1.0.0", + "depd": "^1.1.2", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^1.2.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + } + }, + "koa-bodyparser": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", + "integrity": "sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==", + "dev": true, + "requires": { + "co-body": "^6.0.0", + "copy-to": "^2.0.1" + } + }, + "koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "dev": true + }, + "koa-compress": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/koa-compress/-/koa-compress-3.1.0.tgz", + "integrity": "sha512-0m24/yS/GbhWI+g9FqtvStY+yJwTObwoxOvPok6itVjRen7PBWkjsJ8pre76m+99YybXLKhOJ62mJ268qyBFMQ==", + "dev": true, + "requires": { + "bytes": "^3.0.0", + "compressible": "^2.0.0", + "koa-is-json": "^1.0.0", + "statuses": "^1.0.0" + } + }, + "koa-conditional-get": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/koa-conditional-get/-/koa-conditional-get-2.0.0.tgz", + "integrity": "sha1-pD83I8HQFLcwo07Oit8wuTyCM/I=", + "dev": true + }, + "koa-convert": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", + "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", + "dev": true, + "requires": { + "co": "^4.6.0", + "koa-compose": "^3.0.0" + }, + "dependencies": { + "koa-compose": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", + "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", + "dev": true, + "requires": { + "any-promise": "^1.1.0" + } + } + } + }, + "koa-etag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/koa-etag/-/koa-etag-3.0.0.tgz", + "integrity": "sha1-nvc4Ld1agqsN6xU0FckVg293HT8=", + "dev": true, + "requires": { + "etag": "^1.3.0", + "mz": "^2.1.0" + } + }, + "koa-is-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", + "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=", + "dev": true + }, + "koa-json": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/koa-json/-/koa-json-2.0.2.tgz", + "integrity": "sha1-Nq8U5uofXWRtfESihXAcb4Wk/eQ=", + "dev": true, + "requires": { + "koa-is-json": "1", + "streaming-json-stringify": "3" + } + }, + "koa-morgan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/koa-morgan/-/koa-morgan-1.0.1.tgz", + "integrity": "sha1-CAUuDODYOdPEMXi5CluzQkvvH5k=", + "dev": true, + "requires": { + "morgan": "^1.6.1" + } + }, + "koa-range": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/koa-range/-/koa-range-0.3.0.tgz", + "integrity": "sha1-NYjjSWRzqDmhvSZNKkKx2FvX/qw=", + "dev": true, + "requires": { + "stream-slice": "^0.1.2" + } + }, + "koa-route": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/koa-route/-/koa-route-3.2.0.tgz", + "integrity": "sha1-dimLmaa8+p44yrb+XHmocz51i84=", + "dev": true, + "requires": { + "debug": "*", + "methods": "~1.1.0", + "path-to-regexp": "^1.2.0" + }, + "dependencies": { + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "koa-send": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", + "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "koa-static": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", + "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + } + }, + "level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + }, + "level-concat-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", + "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==" + }, + "level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "requires": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "level-mem": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz", + "integrity": "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==", + "requires": { + "level-packager": "~4.0.0", + "memdown": "~3.0.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "~4.0.0" + } + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + }, + "memdown": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", + "integrity": "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==", + "requires": { + "abstract-leveldown": "~5.0.0", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "level-option-wrap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/level-option-wrap/-/level-option-wrap-1.1.0.tgz", + "integrity": "sha1-rSDmjZ88IsiJdTHMaqevWWse0Sk=", + "requires": { + "defined": "~0.0.0" + } + }, + "level-packager": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz", + "integrity": "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==", + "requires": { + "encoding-down": "~5.0.0", + "levelup": "^3.0.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "~4.0.0" + } + }, + "deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "requires": { + "abstract-leveldown": "~5.0.0", + "inherits": "^2.0.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", + "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "xtend": "^4.0.0" + } + }, + "levelup": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz", + "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==", + "requires": { + "deferred-leveldown": "~4.0.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~3.0.0", + "xtend": "~4.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "level-supports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", + "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", + "requires": { + "xtend": "^4.0.2" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "requires": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "leveldown": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-5.6.0.tgz", + "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", + "requires": { + "abstract-leveldown": "~6.2.1", + "napi-macros": "~2.0.0", + "node-gyp-build": "~4.1.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "node-gyp-build": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", + "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "levelup": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", + "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", + "requires": { + "deferred-leveldown": "~5.3.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~4.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "deferred-leveldown": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", + "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", + "requires": { + "abstract-leveldown": "~6.2.1", + "inherits": "^2.0.3" + } + }, + "level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", + "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0", + "xtend": "^4.0.2" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "load-module": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/load-module/-/load-module-3.0.0.tgz", + "integrity": "sha512-ZqprfrTx4vfH5+1mgpspPh5JYsNyA193NkMUdb3GwpmVqMczOh8cUDJgZBmEZVlSR42JBGYTUxlBAX9LHIBtIA==", + "dev": true, + "requires": { + "array-back": "^4.0.1" + } + }, + "local-web-server": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/local-web-server/-/local-web-server-4.2.1.tgz", + "integrity": "sha512-v71LZool2w7uYA+tDP5HhfjzUxz5SFfcrPPB/zC98yFFawt7A6fcmAr2MR4Q9AHk/A8oyd/wrhEJBJLndwHxNQ==", + "dev": true, + "requires": { + "lws": "^3.1.0", + "lws-basic-auth": "^2.0.0", + "lws-blacklist": "^3.0.0", + "lws-body-parser": "^2.0.0", + "lws-compress": "^2.0.0", + "lws-conditional-get": "^2.0.0", + "lws-cors": "^3.0.0", + "lws-index": "^2.0.0", + "lws-json": "^2.0.0", + "lws-log": "^2.0.0", + "lws-mime": "^2.0.0", + "lws-range": "^3.0.0", + "lws-request-monitor": "^2.0.0", + "lws-rewrite": "^3.1.1", + "lws-spa": "^3.0.0", + "lws-static": "^2.0.0", + "node-version-matches": "^2.0.1" + } + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + }, + "lodash.assignwith": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", + "integrity": "sha1-EnqX8CrcQXUalU0ksN4X4QDgOOs=", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" + }, + "lunr": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", + "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==", + "dev": true + }, + "lws": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lws/-/lws-3.1.0.tgz", + "integrity": "sha512-I8rTgZxz8OJL0hjdlDxs6WpcVG7WSyalVHPQXXK+WPNVjm3KhkT5gV0Qmsgm2FRLbRUp15tso80xmDxMsyt7zA==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^5.1.2", + "array-back": "^4.0.1", + "byte-size": "^6.2.0", + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "create-mixin": "^3.0.0", + "koa": "^2.11.0", + "load-module": "^3.0.0", + "lodash.assignwith": "^4.2.0", + "node-version-matches": "^2.0.1", + "open": "^7.0.4", + "qrcode-terminal": "^0.12.0", + "reduce-flatten": "^3.0.0", + "typical": "^6.0.0", + "walk-back": "^4.0.0" + } + }, + "lws-basic-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-basic-auth/-/lws-basic-auth-2.0.0.tgz", + "integrity": "sha512-zzyoGFLQPuKaQJvHMLmmSyfT6lIvocwcDXllTVW5brD0t0YgHYopILkzja+x+MIlJX/YhNKniaTSasujniYVjw==", + "dev": true, + "requires": { + "basic-auth": "^2.0.1" + } + }, + "lws-blacklist": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lws-blacklist/-/lws-blacklist-3.0.0.tgz", + "integrity": "sha512-KNXGDBmbj+UGfWMBAefe2vrfuWpEQms/9Fd7kfMScTqAKF6nrVoEs4pkxfefArG3bX0bu7jWLyB4tJGma5WC6Q==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "path-to-regexp": "^6.1.0" + } + }, + "lws-body-parser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-body-parser/-/lws-body-parser-2.0.0.tgz", + "integrity": "sha512-QFDzln3sSdKWL9fVNWy2+ZmrKy/XaYRO0/FFB0MBrDCsNnzepeCD4I7rOOfyuphLn42yR8XUpWdcJ3Ii5aauRA==", + "dev": true, + "requires": { + "koa-bodyparser": "^4.2.1" + } + }, + "lws-compress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-compress/-/lws-compress-2.0.0.tgz", + "integrity": "sha512-5qDXI9pukVYWm07WjAOfpItLXKtL8lCHvjmW4RiXULhTRJj1qqBjNcmqReyk8L7NLUKhc+8eqoDDJFKURQEp0w==", + "dev": true, + "requires": { + "koa-compress": "^3.0.0" + } + }, + "lws-conditional-get": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-conditional-get/-/lws-conditional-get-2.0.0.tgz", + "integrity": "sha512-U05yDlFJKIYa7gJZYfnc1HIEuXbKpDJztgkvNYyxCqJC28j/k9ORoNnFNOIHpBh/jlPJgV8x7uH34mIxFAryWA==", + "dev": true, + "requires": { + "koa-conditional-get": "^2.0.0", + "koa-etag": "^3.0.0" + } + }, + "lws-cors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lws-cors/-/lws-cors-3.0.0.tgz", + "integrity": "sha512-diUkoyVZyzLB8LamdtUYYAfJdPAyu/+IjE3ZUcdnNQz9koECe4O2x3SWD7LSV43pd3CKgyiwwSxWJ4hTBZFIvQ==", + "dev": true, + "requires": { + "@koa/cors": "^3.0.0" + } + }, + "lws-index": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-index/-/lws-index-2.0.0.tgz", + "integrity": "sha512-qfkeQmKYnd13LmQubzI5LtFV2N8PJQG4QvgSoefoiB3dWre9k2T4C7ajjOTKO8mgSzYpUEREduNcQcLyt62n0g==", + "dev": true, + "requires": { + "serve-index-75lb": "^2.0.1" + } + }, + "lws-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-json/-/lws-json-2.0.0.tgz", + "integrity": "sha512-vqUFrAQ5BGpkMS2Mm/ZhgvUMi6Tgia7YtESG7pKjNoiSsD+TxncG0nqp8YjUh2xrEzi/SYFc/ed+9ZOl/t0A0g==", + "dev": true, + "requires": { + "koa-json": "^2.0.2" + } + }, + "lws-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-log/-/lws-log-2.0.0.tgz", + "integrity": "sha512-YveoazSZ0Qb1Tljdm8G8yn9c+mAMXgvLMACZzh5aZIk7p8YJwiXf9r1S+xY7wbXEcKG629KfVO0B5G5gRFcyDQ==", + "dev": true, + "requires": { + "koa-morgan": "^1.0.1", + "stream-log-stats": "^3.0.2" + } + }, + "lws-mime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-mime/-/lws-mime-2.0.0.tgz", + "integrity": "sha512-mfrAgRQ5+hkQ7LJ6EAgwnUeymNeYxwLXZY3UQ6C2hSTr7BqMSzm9k5O0C8wWP2dzdhChzITYKwzWbUnAYVBwtA==", + "dev": true + }, + "lws-range": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lws-range/-/lws-range-3.0.0.tgz", + "integrity": "sha512-7ZhA/LqQnKjolKBo/2BFj9DyDDXcJGY3v05TwYRD0qDGrxW4vuatEjluC3SV7ZO/k4PxDLdxuk+RCgL5t3ThtQ==", + "dev": true, + "requires": { + "koa-range": "^0.3.0" + } + }, + "lws-request-monitor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-request-monitor/-/lws-request-monitor-2.0.0.tgz", + "integrity": "sha512-ZTo0/pS42qiejcYlL+wlpurSbDSS0J7pDDohqBx7jjUQkgni2Qd8cPzn/kW8QI82gXgDmdZH+ps0vheLHlgdgg==", + "dev": true, + "requires": { + "byte-size": "^6.2.0" + } + }, + "lws-rewrite": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lws-rewrite/-/lws-rewrite-3.1.1.tgz", + "integrity": "sha512-cOeaPXIlLUVLxS6BZ52QzZVzI8JjCzlWD4RWizB5Hd+0YGO0SPa3Vgk7CIghtAOsSdjtXg/wSOap2H1h+tw8BQ==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "koa-route": "^3.2.0", + "path-to-regexp": "^6.1.0" + } + }, + "lws-spa": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lws-spa/-/lws-spa-3.0.0.tgz", + "integrity": "sha512-Tz10LfuOTUsRG6z+OCJ/vBN+4LQWoAGIJ1R02CFPrDk0pY3rHezM7/cCpq6Z6dXD+ipdNE8alkVn4zL2M+eVGg==", + "dev": true, + "requires": { + "koa-send": "^5.0.0" + } + }, + "lws-static": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-static/-/lws-static-2.0.0.tgz", + "integrity": "sha512-P25A0+IXdkB6Y6gZAG7X0mnaa+FJ8aTiWLUgM5kazaWmruRO7lyhSjitsA3y5TLI3DpPCZn0mWE4SRREujUZLg==", + "dev": true, + "requires": { + "koa-static": "^5.0.0" + } + }, + "marked": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz", + "integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "~4.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, + "merkle-patricia-tree": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz", + "integrity": "sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ==", + "requires": { + "async": "^2.6.1", + "ethereumjs-util": "^5.2.0", + "level-mem": "^3.0.1", + "level-ws": "^1.0.0", + "readable-stream": "^3.0.6", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "level-ws": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz", + "integrity": "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.8", + "xtend": "^4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + }, + "napi-macros": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", + "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" + }, + "node-version-matches": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-version-matches/-/node-version-matches-2.0.1.tgz", + "integrity": "sha512-oqk6+05FC0dNVY5NuXuhPEMq+m1b9ZjS9SIhVE9EjwCHZspnmjSO8npbKAEieinR8GeEgbecoQcYIvI/Kwcf6Q==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + } + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=", + "dev": true + }, + "open": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.1.0.tgz", + "integrity": "sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.1.0.tgz", + "integrity": "sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "qrcode-terminal": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", + "dev": true + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + } + } + }, + "reachdown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reachdown/-/reachdown-1.1.0.tgz", + "integrity": "sha512-6LsdRe4cZyOjw4NnvbhUd/rGG7WQ9HMopPr+kyL018Uci4kijtxcGR5kVb5Ln13k4PEE+fEFQbjfOvNw7cnXmA==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "reduce-flatten": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.0.tgz", + "integrity": "sha512-eczl8wAYBxJ6Egl6I1ECIF+8z6sHu+KE7BzaEDZTpPXKXfy9SUDQlVYwkRcNTjJLC3Iakxbhss50KuT/R6SYfg==", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", + "dev": true, + "requires": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", + "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", + "requires": { + "bn.js": "^4.11.1" + } + }, + "rustbn.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + }, + "secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "serve-index-75lb": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/serve-index-75lb/-/serve-index-75lb-2.0.1.tgz", + "integrity": "sha512-/d9r8bqJlFQcwy0a0nb1KnWAA+Mno+V+VaoKocdkbW5aXKRQd/+4bfnRhQRQr6uEoYwTRJ4xgztOyCJvWcpBpQ==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.18", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "solc": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.4.tgz", + "integrity": "sha512-IVLqAfUkJqgTS0JIgFPeC50ehUeBXu2eE+iU+rqb6UeOyf6w/BB/EsNcTSTpjtUti8BTG/sCd2qVhrWVYy7p0g==", + "dev": true, + "requires": { + "command-exists": "^1.2.8", + "commander": "3.0.2", + "follow-redirects": "^1.12.1", + "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "dependencies": { + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stream-log-stats": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stream-log-stats/-/stream-log-stats-3.0.2.tgz", + "integrity": "sha512-393j7aeF9iRdHvyANqEQU82UQmpw2CTxgsT83caefh+lOxavVLbVrw8Mr4zjXeZLh2+xeHZMKfVx4T0rJ/EchA==", + "dev": true, + "requires": { + "JSONStream": "^1.3.5", + "ansi-escape-sequences": "^5.1.2", + "byte-size": "^6.2.0", + "common-log-format": "^1.0.0", + "lodash.throttle": "^4.1.1", + "stream-via": "^1.0.4", + "table-layout": "~1.0.0" + } + }, + "stream-slice": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", + "integrity": "sha1-LcT04bk2+xPz6zmi3vGTJ5jQeks=", + "dev": true + }, + "stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true + }, + "streaming-json-stringify": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/streaming-json-stringify/-/streaming-json-stringify-3.1.0.tgz", + "integrity": "sha1-gCAEN6mTzDnE/gAmO3s7kDrIevU=", + "dev": true, + "requires": { + "json-stringify-safe": "5", + "readable-stream": "2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "subleveldown": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/subleveldown/-/subleveldown-5.0.1.tgz", + "integrity": "sha512-cVqd/URpp7si1HWu5YqQ3vqQkjuolAwHypY1B4itPlS71/lsf6TQPZ2Y0ijT22EYVkvH5ove9JFJf4u7VGPuZw==", + "requires": { + "abstract-leveldown": "^6.3.0", + "encoding-down": "^6.2.0", + "inherits": "^2.0.3", + "level-option-wrap": "^1.1.0", + "levelup": "^4.4.0", + "reachdown": "^1.1.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", + "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "encoding-down": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", + "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", + "requires": { + "abstract-leveldown": "^6.2.1", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0" + } + }, + "level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "requires": { + "buffer": "^5.6.0" + } + }, + "level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "requires": { + "errno": "~0.1.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table-layout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.1.tgz", + "integrity": "sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "requires": { + "rimraf": "^3.0.0" + } + }, + "tmp-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.2.tgz", + "integrity": "sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA==", + "requires": { + "tmp": "^0.2.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "ts-transformer-inline-file": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ts-transformer-inline-file/-/ts-transformer-inline-file-0.1.1.tgz", + "integrity": "sha512-2bPkAFjATsRG4ld8TFTUqn4TvEdXLQf/wwGsepFeRKSXLPqFRhdUHusAGPB1/Zif3CVjppD+bfne58gynd8RfQ==", + "dev": true + }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true + }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedoc": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.8.tgz", + "integrity": "sha512-/OyrHCJ8jtzu+QZ+771YaxQ9s4g5Z3XsQE3Ma7q+BL392xxBn4UMvvCdVnqKC2T/dz03/VXSLVKOP3lHmDdc/w==", + "dev": true, + "requires": { + "fs-extra": "^8.1.0", + "handlebars": "^4.7.6", + "highlight.js": "^10.0.0", + "lodash": "^4.17.15", + "lunr": "^2.3.8", + "marked": "1.0.0", + "minimatch": "^3.0.0", + "progress": "^2.0.3", + "shelljs": "^0.8.4", + "typedoc-default-themes": "^0.10.2" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "typedoc-default-themes": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.10.2.tgz", + "integrity": "sha512-zo09yRj+xwLFE3hyhJeVHWRSPuKEIAsFK5r2u47KL/HBKqpwdUSanoaz5L34IKiSATFrjG5ywmIu98hPVMfxZg==", + "dev": true, + "requires": { + "lunr": "^2.3.8" + } + }, + "typical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", + "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", + "dev": true + }, + "uWebSockets.js": { + "version": "github:uNetworking/uWebSockets.js#3dbec7b56d627193e20705844b6bd10e49848b8c", + "from": "github:uNetworking/uWebSockets.js#v18.4.0", + "dev": true + }, + "uglify-js": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.0.tgz", + "integrity": "sha512-Esj5HG5WAyrLIdYU74Z3JdG2PxdIusvj6IWHMtlyESxc7kcDz7zYlYjpnSokn1UbpV0d/QX9fan7gkCNd/9BQA==", + "dev": true, + "optional": true + }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "dev": true + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "walk-back": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz", + "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wordwrapjs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz", + "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==", + "dev": true, + "requires": { + "reduce-flatten": "^2.0.0", + "typical": "^5.0.0" + }, + "dependencies": { + "reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "~0.4.0" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "ylru": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", + "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==", + "dev": true + } + } +} diff --git a/src/chains/ethereum/package.json b/src/chains/ethereum/package.json new file mode 100644 index 0000000000..eab86a37a9 --- /dev/null +++ b/src/chains/ethereum/package.json @@ -0,0 +1,92 @@ +{ + "name": "@ganache/ethereum", + "version": "0.1.0", + "description": "Ganache's Ethereum client implementation", + "author": "David Murdoch (https://davidmurdoch.com)", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/ethereum#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "source": "index.ts", + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "lib" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/chains/ethereum" + }, + "scripts": { + "docs.build": "rm -rf ./lib/docs ./lib/api.json && typedoc --options ./typedoc.json --readme ./README.md --out ./lib/docs --json ./lib/api.json src/api.ts && npm run docs.post-process", + "docs.post-process": "node ./scripts/post-process-docs.js", + "tsc": "ttsc", + "test": "nyc --reporter lcov npm run mocha", + "mocha": "cross-env TS_NODE_COMPILER=ttypescript TS_NODE_FILES=true mocha --exit --check-leaks --throw-deprecation --trace-warnings --require ts-node/register 'tests/**/*.test.ts'" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ganache-ethereum", + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling" + ], + "dependencies": { + "@ganache/options": "^0.1.0", + "@ganache/promise-queue": "^0.1.0", + "@ganache/utils": "^0.1.0", + "@types/keccak": "3.0.1", + "bip39": "3.0.2", + "emittery": "0.7.2", + "eth-sig-util": "2.5.3", + "ethereumjs-abi": "0.6.8", + "ethereumjs-account": "3.0.0", + "ethereumjs-block": "2.2.2", + "ethereumjs-common": "1.5.2", + "ethereumjs-tx": "2.1.2", + "ethereumjs-util": "7.0.7", + "ethereumjs-vm": "4.2.0", + "hdkey": "2.0.1", + "keccak": "3.0.0", + "leveldown": "5.6.0", + "levelup": "4.4.0", + "lodash.clonedeep": "4.5.0", + "merkle-patricia-tree": "3.0.0", + "scrypt-js": "3.0.1", + "secp256k1": "4.0.2", + "seedrandom": "3.0.5", + "subleveldown": "5.0.1", + "tmp-promise": "3.0.2" + }, + "devDependencies": { + "@trufflesuite/typedoc-default-themes": "0.6.1", + "@types/fs-extra": "9.0.2", + "@types/lodash.clonedeep": "4.5.6", + "@types/secp256k1": "4.0.1", + "@types/seedrandom": "2.4.28", + "@types/ws": "7.2.7", + "cheerio": "1.0.0-rc.3", + "fs-extra": "9.0.1", + "local-web-server": "4.2.1", + "solc": "0.7.4", + "ts-transformer-inline-file": "0.1.1", + "typedoc": "0.17.8", + "uWebSockets.js": "github:uNetworking/uWebSockets.js#v18.4.0" + } +} diff --git a/src/chains/ethereum/scripts/post-process-docs.js b/src/chains/ethereum/scripts/post-process-docs.js new file mode 100644 index 0000000000..5db1da3f63 --- /dev/null +++ b/src/chains/ethereum/scripts/post-process-docs.js @@ -0,0 +1,23 @@ +const cheerio = require("cheerio"); +const { readFileSync, writeFileSync } = require("fs"); +const { randomBytes } = require("crypto"); +const $ = cheerio.load( + readFileSync("./lib/docs/classes/_api_.ethereumapi.html") +); + +$(`.tsd-page-title`).after(``); + +$(".runkit-example").each(function () { + const sanitizedCode = $(this) + .text() + .replace(/;(\s+)/gi, ";\n") + .trim(); + $(this).text(""); + const id = randomBytes(4).toString("hex"); + $(this).attr("id", id).html(); + $(this).prepend( + `` + ); +}); + +writeFileSync("./lib/docs/classes/_api_.ethereumapi.html", $.html()); diff --git a/src/chains/ethereum/src/@types/ethereumjs-block/header.d.ts b/src/chains/ethereum/src/@types/ethereumjs-block/header.d.ts new file mode 100644 index 0000000000..6f69e9149e --- /dev/null +++ b/src/chains/ethereum/src/@types/ethereumjs-block/header.d.ts @@ -0,0 +1,62 @@ +declare module "ethereumjs-block/header" { + import BN from "bn.js"; + import { Block } from "ethereumjs-block"; + import { Blockchain } from "ethereumjs-blockchain"; + + type LargeNumber = string | Buffer | BN; + type Callback = (err: Error | null, result: T) => void; + + export interface IBlockHeader { + parentHash: Buffer; + uncleHash: Buffer; + coinbase: Buffer; + stateRoot: Buffer; + transactionTrie: Buffer; + receiptTrie: Buffer; + bloom: Buffer; + difficulty: Buffer; + number: Buffer; + gasLimit: Buffer; + gasUsed: Buffer; + timestamp: Buffer; + extraData: Buffer; + } + + export class BlockHeader { + public raw!: Buffer[]; + public parentHash!: Buffer; + public uncleHash!: Buffer; + public coinbase!: Buffer; + public stateRoot!: Buffer; + public transactionsTrie!: Buffer; + public receiptTrie!: Buffer; + public bloom!: Buffer; + public difficulty!: Buffer; + public number!: Buffer; + public gasLimit!: Buffer; + public gasUsed!: Buffer; + public timestamp!: Buffer; + public extraData!: Buffer; + public mixHash!: Buffer; + public nonce!: Buffer; + + constructor( + data: Buffer | PrefixedHexString | BufferLike[] | BlockHeaderData = {}, + opts: ChainOptions = {} + ); + serialize(): Buffer; + canonicalDifficulty(block: Block): BN; + validateDifficulty(block: Block): boolean; + validateGasLimit(block: Block): boolean; + validate( + blockChain: Blockchain, + height: BN | Callback, + cb?: Callback + ): void; + hash(): Buffer; + isGenesis(): boolean; + toJSON(labeled: boolean): object; + } + + export default BlockHeader; +} diff --git a/src/chains/ethereum/src/@types/ethereumjs-block/index.d.ts b/src/chains/ethereum/src/@types/ethereumjs-block/index.d.ts new file mode 100644 index 0000000000..4c5d858c8e --- /dev/null +++ b/src/chains/ethereum/src/@types/ethereumjs-block/index.d.ts @@ -0,0 +1,43 @@ +declare module "ethereumjs-block" { + import BN from "bn.js"; + import { Blockchain } from "ethereumjs-blockchain"; + import Transaction from "ethereumjs-tx"; + import BlockHeader from "ethereumjs-block/header"; + import Trie from "merkle-patricia-tree/baseTrie"; + + type LargeNumber = string | Buffer | BN; + type Callback = (err: Error | null, result: T) => void; + + export interface IBlock { + transactions: Transaction[]; + uncleHeaders: BlockHeader[]; + txTrie: Trie; + header: BlockHeader; + } + + export class Block { + transactions: Transaction[]; + uncleHeaders: BlockHeader[]; + txTrie: Trie; + header: BlockHeader; + raw: Buffer[]; + + constructor( + data: Buffer | [Buffer[], Buffer[], Buffer[]] | BlockData = {}, + opts: ChainOptions = {} + ); + hash(): Buffer; + isGenesis(): boolean; + setGenesisParams(): void; + serialize(rlpEncode: boolean): Buffer; + genTxTrie(cb: Callback): void; + validateTransactionTrie(): boolean; + validateTransactions(sringError: boolean): boolean | string; + validate(blockChain: Blockchain, cb: Callback): void; + validateUnclesHash(): boolean; + validateUncles(blockChain: Blockchain, cb: Callback): void; + toJSON(labeled?: boolean): object; + } + + export default Block; +} diff --git a/src/chains/ethereum/src/@types/ethereumjs-util/index.d.ts b/src/chains/ethereum/src/@types/ethereumjs-util/index.d.ts new file mode 100644 index 0000000000..24678e1695 --- /dev/null +++ b/src/chains/ethereum/src/@types/ethereumjs-util/index.d.ts @@ -0,0 +1,8 @@ +import "ethereumjs-util"; + +declare module "ethereumjs-util" { + export declare const publicToAddress: ( + pubKey: Buffer, + sanitize?: boolean + ) => Buffer; +} diff --git a/src/chains/ethereum/src/@types/hdkey/index.d.ts b/src/chains/ethereum/src/@types/hdkey/index.d.ts new file mode 100644 index 0000000000..486d9d12a7 --- /dev/null +++ b/src/chains/ethereum/src/@types/hdkey/index.d.ts @@ -0,0 +1,37 @@ +declare module "hdkey" { + type HDKeyJSON = { + xpriv: string; + xpub: string; + }; + type HDKeyVersions = { private: number; public: number }; + export default class HDKey { + public versions: HDKeyVersions; + public depth: number; + public index: number; + public readonly parentFingerprint: number; + public readonly fingerprint: number; + public readonly identifier?: Uint8Array; + public readonly pubKeyHash?: Uint8Array; + public readonly privateKey?: Buffer; + public publicKey?: Buffer; + public readonly privateExtendedKey?: string; + public readonly publicExtendedKey: string; + public readonly chainCode?: Buffer; + public derive: (path: string) => HDKey; + public deriveChild: (index: number) => HDKey; + public sign: (hash: Buffer) => Buffer; + public verify: (hash: Buffer, signature: Buffer) => boolean; + public wipePrivateData: () => HDKey; + public toJSON: (path: string) => HDKeyJSON; + public static fromMasterSeed: ( + seedBuffer: Buffer, + version?: HDKeyVersions + ) => HDKey; + public static fromExtendedKey: ( + base58key: string, + version?: HDKeyVersions + ) => HDKey; + public static fromJSON: (obj: HDKeyJSON) => HDKey; + public static HARDENED_OFFSET: 0x80000000; + } +} diff --git a/src/chains/ethereum/src/@types/levelup/index.d.ts b/src/chains/ethereum/src/@types/levelup/index.d.ts new file mode 100644 index 0000000000..8274b83162 --- /dev/null +++ b/src/chains/ethereum/src/@types/levelup/index.d.ts @@ -0,0 +1,128 @@ +/// + +declare module "levelup" { + import { AbstractLevelDOWN } from "abstract-leveldown"; + + export = levelup; + + var levelup: levelup.LevelUpConstructor; + + namespace levelup { + interface CustomEncoding { + encode(val: any): Buffer | string; + decode(val: Buffer | string): any; + buffer: boolean; + type: string; + } + + type Encoding = string | CustomEncoding; + + interface Batch { + type: string; + key: any; + value?: any; + keyEncoding?: Encoding; + valueEncoding?: Encoding; + } + + interface LevelUpBase { + open(callback?: (error: any) => any): void; + + close(callback?: (error: any) => any): void; + + put(key: any, value: any): Promise; + put(key: any, value: any, callback: (error: any) => any): void; + put(key: any, value: any, options: { sync?: boolean }): Promise; + put( + key: any, + value: any, + options: { sync?: boolean }, + callback: (error: any) => any + ): void; + + get(key: any): Promise; + get(key: any, callback: (error: any, value: any) => any): void; + get( + key: any, + options: { keyEncoding?: Encoding; fillCache?: boolean } + ): Promise; + get( + key: any, + options: { keyEncoding?: Encoding; fillCache?: boolean }, + callback: (error: any, value: any) => any + ): void; + + del(key: any): Promise; + del(key: any, callback: (error: any) => any): void; + del( + key: any, + options: { keyEncoding?: Encoding; sync?: boolean } + ): Promise; + del( + key: any, + options: { keyEncoding?: Encoding; sync?: boolean }, + callback: (error: any) => any + ): void; + + batch(): LevelUpChain; + batch(array: BatchType[]): Promise; + batch(array: BatchType[], callback: (error?: any) => any): void; + batch( + array: BatchType[], + options: { + keyEncoding?: Encoding; + valueEncoding?: Encoding; + sync?: boolean; + } + ): Promise; + batch( + array: BatchType[], + options: { + keyEncoding?: Encoding; + valueEncoding?: Encoding; + sync?: boolean; + }, + callback: (error?: any) => any + ): void; + + isOpen(): boolean; + isClosed(): boolean; + createReadStream(options?: any): any; + createKeyStream(options?: any): any; + createValueStream(options?: any): any; + } + + type LevelUp = LevelUpBase; + + interface LevelUpChain { + put(key: any, value: any): LevelUpChain; + put(key: any, value: any, options?: { sync?: boolean }): LevelUpChain; + del(key: any): LevelUpChain; + del( + key: any, + options?: { keyEncoding?: Encoding; sync?: boolean } + ): LevelUpChain; + clear(): LevelUpChain; + write(): Promise; + write(callback?: (error?: any) => any): void; + } + + interface levelupOptions< + K = any, + V = any, + O = any, + PO = any, + GO = any, + DO = any, + IO = any, + BO = any + > { + db?: (location: string) => AbstractLevelDOWN; + } + + interface LevelUpConstructor { + (location: string, options?: levelupOptions): LevelUp; + (options: levelupOptions): LevelUp; + } + } +} diff --git a/src/chains/ethereum/src/@types/merkle-patricia-tree/baseTrie.ts b/src/chains/ethereum/src/@types/merkle-patricia-tree/baseTrie.ts new file mode 100644 index 0000000000..3ab25a0f0c --- /dev/null +++ b/src/chains/ethereum/src/@types/merkle-patricia-tree/baseTrie.ts @@ -0,0 +1,45 @@ +declare module "merkle-patricia-tree/baseTrie" { + import BN from "bn.js"; + + import TrieNode from "merkle-patricia-tree/trieNode"; + import ReadStream from "merkle-patricia-tree/readStream"; + + type Callback = (err: Error | null, result: T) => void; + type FindPathCallback = ( + err: Error, + node: TrieNode, + keyRemainder: Buffer, + stack: TrieNode[] + ) => void; + type LargeNumber = string | Buffer | BN; + + // Rather than using LevelUp here, specify the minimal interface we need + // so that other structurally identical types can be used in its place + export interface Database { + get(key: Buffer, opt: any, cb: Callback): void; + put(key: Buffer, val: Buffer, options: any, cb: Callback): void; + del(key: Buffer, opt: any, cb: Callback): void; + } + + export interface BatchOperation { + type: "del" | "put"; + key: LargeNumber; + value?: LargeNumber; + } + + export class Trie { + root: Buffer; + constructor(db: Database, root: Buffer); + get(key: LargeNumber, cb: Callback): void; + put(key: LargeNumber, value: LargeNumber, cb: Callback): void; + del(key: LargeNumber, cb: Callback): void; + getRaw(key: LargeNumber, cb: Callback): void; + findPath(key: LargeNumber, cb: FindPathCallback): void; + createReadStream(): ReadStream; + copy(): Trie; + batch(ops: BatchOperation[], cb: (err: Error[]) => void): void; + checkRoot(root: LargeNumber, cb: Callback): void; + } + + export default Trie; +} diff --git a/src/chains/ethereum/src/@types/merkle-patricia-tree/index.d.ts b/src/chains/ethereum/src/@types/merkle-patricia-tree/index.d.ts new file mode 100644 index 0000000000..098dcd79ab --- /dev/null +++ b/src/chains/ethereum/src/@types/merkle-patricia-tree/index.d.ts @@ -0,0 +1,38 @@ +declare module "merkle-patricia-tree" { + import BN from "bn.js"; + import { Readable } from "stream"; + + import { Trie, Database } from "merkle-patricia-tree/baseTrie"; + import TrieNode from "merkle-patricia-tree/trieNode"; + + type MerkleProof = TrieNode[]; + type Callback = (err: Error | null, result: T) => void; + type LargeNumber = string | Buffer | BN; + + export class ScratchReadStream extends Readable { + trie: Trie; + } + + export class CheckpointTrie extends Trie { + readonly isCheckpoint: boolean; + + root: Buffer; + constructor(db: Database, root: Buffer); + get(key: LargeNumber, cb: Callback): void; + put(key: LargeNumber, value: LargeNumber, cb: Callback): void; + copy(): Trie; + + checkpoint(): void; + commit(cb: Callback): void; + revert(cb: Callback): void; + createScratchReadStream(scratch: Database): ScratchReadStream; + static prove(trie: Trie, key: LargeNumber, cb: Callback): void; + static verifyProof( + rootHash: LargeNumber, + key: LargeNumber, + proof: MerkleProof, + cb: Callback + ): void; + } + export default CheckpointTrie; +} diff --git a/src/chains/ethereum/src/@types/merkle-patricia-tree/readStream.ts b/src/chains/ethereum/src/@types/merkle-patricia-tree/readStream.ts new file mode 100644 index 0000000000..3972b94c62 --- /dev/null +++ b/src/chains/ethereum/src/@types/merkle-patricia-tree/readStream.ts @@ -0,0 +1,10 @@ +declare module "merkle-patricia-tree/readStream" { + import Trie from "merkle-patricia-tree/baseTrie"; + import { Readable } from "stream"; + + export class TrieReadStream extends Readable { + constructor(trie: Trie); + } + + export default TrieReadStream; +} diff --git a/src/chains/ethereum/src/@types/merkle-patricia-tree/trieNode.ts b/src/chains/ethereum/src/@types/merkle-patricia-tree/trieNode.ts new file mode 100644 index 0000000000..25fe0e6d67 --- /dev/null +++ b/src/chains/ethereum/src/@types/merkle-patricia-tree/trieNode.ts @@ -0,0 +1,45 @@ +declare module "merkle-patricia-tree/trieNode" { + import BN from "bn.js"; + + type LargeNumber = string | Buffer | BN; + type Callback = (err: Error | null, result: T) => void; + type NodeType = "branch" | "leaf" | "extension"; + type NibbleArray = number[]; + + export class TrieNode { + value: Buffer; + key: Buffer; + type: NodeType; + raw: number[]; + + constructor( + type: NodeType | NibbleArray, + key?: NibbleArray, + value?: NibbleArray + ); + parseNode(node: NibbleArray): void; + setValue(key: NibbleArray, value: NibbleArray): void; + getValue(key: NibbleArray): NibbleArray; + setKey(key: NibbleArray): void; + getKey(): NibbleArray; + serialize(): Buffer; + hash(): Buffer; + toString: string; + getChildren(): TrieNode[]; + static addHexPrefix(key: NibbleArray, terminator: boolean): NibbleArray; + static removeHexPrefix(val: NibbleArray): NibbleArray; + static isTerminator(key: NibbleArray): boolean; + static stringToNibbles(key: LargeNumber): NibbleArray; + static nibblesToBuffer(arr: NibbleArray): Buffer; + static getNodeType(node: TrieNode): NodeType; + } + + function addHexPrefix(key: NibbleArray, terminator: boolean): NibbleArray; + function removeHexPrefix(val: NibbleArray): NibbleArray; + function isTerminator(key: NibbleArray): boolean; + function stringToNibbles(key: LargeNumber): NibbleArray; + function nibblesToBuffer(arr: NibbleArray): Buffer; + function getNodeType(node: TrieNode): NodeType; + + export default TrieNode; +} diff --git a/src/chains/ethereum/src/api.ts b/src/chains/ethereum/src/api.ts new file mode 100644 index 0000000000..0bc3f12cf6 --- /dev/null +++ b/src/chains/ethereum/src/api.ts @@ -0,0 +1,2047 @@ +//#region Imports +import { RuntimeBlock, Block } from "./things/runtime-block"; +import { + toRpcSig, + KECCAK256_NULL, + ecsign, + hashPersonalMessage +} from "ethereumjs-util"; +import { TypedData as NotTypedData, signTypedData_v4 } from "eth-sig-util"; +import { EthereumInternalOptions } from "./options"; +import { types, Data, Quantity } from "@ganache/utils"; +import Blockchain from "./blockchain"; +import Tag from "./things/tags"; +import { VM_EXCEPTION, VM_EXCEPTIONS } from "./errors/errors"; +import Address from "./things/address"; +import Transaction from "./things/transaction"; +import Wallet from "./wallet"; +import { decode as rlpDecode } from "rlp"; +import { $INLINE_JSON } from "ts-transformer-inline-file"; +import keccak from "keccak"; + +import { PromiEvent, utils } from "@ganache/utils"; +import Emittery from "emittery"; +import Common from "ethereumjs-common"; +import BlockLogs from "./things/blocklogs"; +import EthereumAccount from "ethereumjs-account"; +import estimateGas from "./helpers/gas-estimator"; +import CodedError, { ErrorCodes } from "./errors/coded-error"; +import { WhisperPostObject } from "./types/shh"; +import { + BaseFilterArgs, + Filter, + FilterArgs, + FilterTypes, + RangeFilterArgs +} from "./types/filters"; +import { assertArgLength } from "./helpers/assert-arg-length"; +import Account from "./things/account"; +import { SubscriptionId, SubscriptionName } from "./types/subscriptions"; +import { + parseFilter, + parseFilterDetails, + parseFilterRange +} from "./helpers/filter-parsing"; +import { Hardfork } from "./options/chain-options"; + +// Read in the current ganache version from core's package.json +const { version } = $INLINE_JSON("../../../packages/ganache/package.json"); +//#endregion + +//#region Constants +const RPCQUANTITY_ZERO = utils.RPCQUANTITY_ZERO; +const CLIENT_VERSION = `Ganache/v${version}/EthereumJS TestRPC/v${version}/ethereum-js`; +const PROTOCOL_VERSION = Data.from("0x3f"); +const RPC_MODULES = { + eth: "1.0", + net: "1.0", + rpc: "1.0", + web3: "1.0", + evm: "1.0", + personal: "1.0" +} as const; +const KNOWN_CHAINIDS = new Set([1, 3, 4, 5, 42]); +//#endregion + +//#region misc types +type TypedData = Exclude< + Parameters[1]["data"], + NotTypedData +>; +//#endregion + +//#region helpers +function assertExceptionalTransactions(transactions: Transaction[]) { + let baseError: string = null; + let errors: string[]; + const data = {}; + + transactions.forEach(transaction => { + if (transaction.execException) { + if (baseError) { + baseError = VM_EXCEPTIONS; + errors.push( + `${Data.from(transaction.hash(), 32).toString()}: ${ + transaction.execException + }\n` + ); + data[transaction.execException.data.hash] = + transaction.execException.data; + } else { + baseError = VM_EXCEPTION; + errors = [transaction.execException.message]; + data[transaction.execException.data.hash] = + transaction.execException.data; + } + } + }); + + if (baseError) { + const err = new Error(baseError + errors.join("\n")); + (err as any).data = data; + throw err; + } +} + +function parseCoinbaseAddress( + coinbase: string | number | Address, + initialAccounts: Account[] +) { + switch (typeof coinbase) { + case "object": + return coinbase; + case "number": + const account = initialAccounts[coinbase]; + if (account) { + return account.address; + } else { + throw new Error(`invalid coinbase address index: ${coinbase}`); + } + case "string": + return Address.from(coinbase); + default: { + throw new Error( + `coinbase address must be string or number, received: ${coinbase}` + ); + } + } +} + +function createCommon(chainId: number, networkId: number, hardfork: Hardfork) { + return Common.forCustomChain( + // if we were given a chain id that matches a real chain, use it + // NOTE: I don't think Common serves a purpose ther than instructing the + // VM what hardfork is in use. But just incase things change in the future + // its configured "more correctly" here. + KNOWN_CHAINIDS.has(chainId) ? chainId : 1, + { + name: "ganache", + networkId: networkId, + chainId: chainId, + comment: "Local test network" + }, + hardfork + ); +} +//#endregion helpers + +export default class EthereumApi implements types.Api { + readonly [index: string]: (...args: any) => Promise; + + readonly #getId = (id => () => Quantity.from(++id))(0); + readonly #common: Common; + readonly #filters = new Map(); + readonly #subscriptions = new Map(); + readonly #blockchain: Blockchain; + readonly #options: EthereumInternalOptions; + readonly #wallet: Wallet; + + /** + * This is the Ethereum API that the provider interacts with. + * The only methods permitted on the prototype are the supported json-rpc + * methods. + * @param options + * @param ready Callback for when the API is fully initialized + */ + constructor( + options: EthereumInternalOptions, + wallet: Wallet, + emitter: Emittery.Typed<{ message: any }, "connect" | "disconnect"> + ) { + this.#options = options; + + const { chain } = options; + const { initialAccounts } = (this.#wallet = wallet); + const coinbaseAddress = parseCoinbaseAddress( + options.miner.coinbase, + initialAccounts + ); + const common = (this.#common = createCommon( + chain.chainId, + chain.networkId, + chain.hardfork + )); + + const blockchain = (this.#blockchain = new Blockchain( + options, + common, + initialAccounts, + coinbaseAddress + )); + blockchain.on("start", () => emitter.emit("connect")); + emitter.on("disconnect", blockchain.stop.bind(blockchain)); + } + + //#region db + /** + * Stores a string in the local database. + * + * @param {String} dbName - Database name. + * @param {String} key - Key name. + * @param {String} value - String to store. + * @returns returns true if the value was stored, otherwise false. + */ + @assertArgLength(3) + async db_putString(dbName: string, key: string, value: string) { + return false; + } + + /** + * Returns string from the local database + * + * @param {String} dbName - Database name. + * @param {String} key - Key name. + * @returns The previously stored string. + */ + @assertArgLength(2) + async db_getString(dbName: string, key: string) { + return ""; + } + + /** + * Stores binary data in the local database. + * + * @param {String} dbName - Database name. + * @param {String} key - Key name. + * @param {DATA} data - Data to store. + * @returns true if the value was stored, otherwise false. + */ + @assertArgLength(3) + async db_putHex(dbName: string, key: string, data: string) { + return false; + } + + /** + * Returns binary data from the local database + * + * @param {String} dbName - Database name. + * @param {String} key - Key name. + * @returns The previously stored data. + */ + @assertArgLength(2) + async db_getHex(dbName: string, key: string) { + return "0x00"; + } + //#endregion + + //#region bzz + @assertArgLength(0) + async bzz_hive() { + return []; + } + + @assertArgLength(0) + async bzz_info() { + return []; + } + //#endregion + + //#region evm + /** + * Force a single block to be mined. + * + * Mines a block independent of whether or not mining is started or stopped. + * Will mine an empty block if there are no available transactions to mine. + * + * @param timestamp the timestamp a block should setup as the mining time. + */ + @assertArgLength(0, 1) + async evm_mine(timestamp?: number) { + const transactions = await this.#blockchain.mine(-1, timestamp, true); + if (this.#options.chain.vmErrorsOnRPCResponse) { + assertExceptionalTransactions(transactions); + } + + return "0x0"; + } + + @assertArgLength(3, 4) + async evm_setStorageAt( + address: string, + position: bigint | number, + storage: string, + blockNumber: string | Buffer | Tag = Tag.LATEST + ) { + const blockProm = this.#blockchain.blocks.getRaw(blockNumber); + + const trie = this.#blockchain.trie.copy(); + const getFromTrie = (address: Buffer): Promise => + new Promise((resolve, reject) => { + trie.get(address, (err, data) => { + if (err) return void reject(err); + resolve(data); + }); + }); + const block = await blockProm; + if (!block) throw new Error("header not found"); + + const blockData = (rlpDecode(block) as unknown) as [ + [Buffer, Buffer, Buffer, Buffer /* stateRoot */] /* header */, + Buffer[], + Buffer[] + ]; + const headerData = blockData[0]; + const blockStateRoot = headerData[3]; + trie.root = blockStateRoot; + + const addressDataPromise = getFromTrie(Address.from(address).toBuffer()); + + const posBuff = Quantity.from(position).toBuffer(); + const length = posBuff.length; + let paddedPosBuff: Buffer; + if (length < 32) { + // storage locations are 32 bytes wide, so we need to expand any value + // given to 32 bytes. + paddedPosBuff = Buffer.allocUnsafe(32).fill(0); + posBuff.copy(paddedPosBuff, 32 - length); + } else if (length === 32) { + paddedPosBuff = posBuff; + } else { + // if the position value we're passed is > 32 bytes, truncate it. This is + // what geth does. + paddedPosBuff = posBuff.slice(-32); + } + + const addressData = await addressDataPromise; + // An address's stateRoot is stored in the 3rd rlp entry + this.#blockchain.trie.root = ((rlpDecode(addressData) as any) as [ + Buffer /*nonce*/, + Buffer /*amount*/, + Buffer /*stateRoot*/, + Buffer /*codeHash*/ + ])[2]; + + return new Promise((resolve, reject) => { + this.#blockchain.trie.put(paddedPosBuff, storage, err => { + if (err) return reject(err); + resolve(void 0); + }); + }); + } + + /** + * Sets the given account's nonce to the specified value. Mines a new block + * before returning. + * + * Warning: this will result in an invalid state tree. + * + * @param address + * @param nonce + * @returns true if it worked + */ + @assertArgLength(2) + async evm_setAccountNonce(address: string, nonce: string) { + return new Promise((resolve, reject) => { + const buffer = Address.from(address).toBuffer(); + const blockchain = this.#blockchain; + const stateManager = blockchain.vm.stateManager; + stateManager.getAccount( + buffer, + (err: Error, account: EthereumAccount) => { + if (err) { + reject(err); + return; + } + account.nonce = Quantity.from(nonce).toBuffer(); + stateManager.putAccount(buffer, account, (err: Error) => { + if (err) { + reject(err); + return; + } + + blockchain.mine(0).then(() => resolve(true), reject); + }); + } + ); + }); + } + + /** + * Jump forward in time by the given amount of time, in seconds. + * @param seconds Must be greater than or equal to `0` + * @returns Returns the total time adjustment, in seconds. + */ + @assertArgLength(1) + async evm_increaseTime(seconds: number | string) { + const milliseconds = + (typeof seconds === "number" + ? seconds + : Quantity.from(seconds).toNumber()) * 1000; + return Math.floor(this.#blockchain.increaseTime(milliseconds) / 1000); + } + + /** + * Sets the internal clock time to the given timestamp. + * + * Warning: This will allow you to move *backwards* in time, which may cause + * new blocks to appear to be mined before old blocks. This is will result in + * an invalid state. + * + * @param timestamp JavaScript timestamp (millisecond precision) + * @returns The amount of *seconds* between the given timestamp and now. + */ + @assertArgLength(0, 1) + async evm_setTime(time: string | Date | number) { + let t: number; + switch (typeof time) { + case "object": + t = time.getTime(); + break; + case "number": + t = time; + break; + default: + t = Quantity.from(time).toNumber(); + break; + } + return Math.floor(this.#blockchain.setTime(t) / 1000); + } + + /** + * Revert the state of the blockchain to a previous snapshot. Takes a single + * parameter, which is the snapshot id to revert to. This deletes the given + * snapshot, as well as any snapshots taken after (Ex: reverting to id 0x1 + * will delete snapshots with ids 0x1, 0x2, etc... If no snapshot id is + * passed it will revert to the latest snapshot. + * + * @param snapshotId the snapshot id to revert + * @returns `true` if a snapshot was reverted, otherwise `false` + * + * @example + * ```javascript + * const snapshotId = await provider.send("evm_snapshot"); + * const isReverted = await provider.send("evm_revert", [snapshotId]); + * ``` + * + * @example + * ```javascript + * const provider = ganache.provider(); + * const [from, to] = await provider.send("eth_accounts"); + * const startingBalance = BigInt(await provider.send("eth_getBalance", [from])); + * + * // take a snapshot + * const snapshotId = await provider.send("evm_snapshot"); + * + * // send value to another account (over-simplified example) + * await provider.send("eth_subscribe", ["newHeads"]); + * await provider.send("eth_sendTransaction", [{from, to, value: "0xffff"}]); + * await provider.once("message"); // Note: `await provider.once` is non-standard + * + * // ensure balance has updated + * const newBalance = await provider.send("eth_getBalance", [from]); + * assert(BigInt(newBalance) < startingBalance); + * + * // revert the snapshot + * const isReverted = await provider.send("evm_revert", [snapshotId]); + * assert(isReverted); + * + * const endingBalance = await provider.send("eth_getBalance", [from]); + * assert.strictEqual(BigInt(endingBalance), startingBalance); + * ``` + */ + @assertArgLength(1) + async evm_revert(snapshotId: string | number) { + return this.#blockchain.revert(Quantity.from(snapshotId)); + } + + /** + * Snapshot the state of the blockchain at the current block. Takes no + * parameters. Returns the id of the snapshot that was created. A snapshot can + * only be reverted once. After a successful `evm_revert`, the same snapshot + * id cannot be used again. Consider creating a new snapshot after each + * `evm_revert` if you need to revert to the same point multiple times. + * + * @returns The hex-encoded identifier for this snapshot + * + * @example + * ```javascript + * const snapshotId = await provider.send("evm_snapshot"); + * ``` + * + * @example + * ```javascript + * const provider = ganache.provider(); + * const [from, to] = await provider.send("eth_accounts"); + * const startingBalance = BigInt(await provider.send("eth_getBalance", [from])); + * + * // take a snapshot + * const snapshotId = await provider.send("evm_snapshot"); + * + * // send value to another account (over-simplified example) + * await provider.send("eth_subscribe", ["newHeads"]); + * await provider.send("eth_sendTransaction", [{from, to, value: "0xffff"}]); + * await provider.once("message"); // Note: `await provider.once` is non-standard + * + * // ensure balance has updated + * const newBalance = await provider.send("eth_getBalance", [from]); + * assert(BigInt(newBalance) < startingBalance); + * + * // revert the snapshot + * const isReverted = await provider.send("evm_revert", [snapshotId]); + * assert(isReverted); + * + * const endingBalance = await provider.send("eth_getBalance", [from]); + * assert.strictEqual(BigInt(endingBalance), startingBalance); + * ``` + */ + async evm_snapshot() { + return Quantity.from(this.#blockchain.snapshot()); + } + + /** + * Unlocks any unknown account. + * @param address address the address of the account to unlock + * @param duration (default: disabled) Duration in seconds how long the account + * should remain unlocked for. Set to 0 to disable automatic locking. + * @returns `true` if the account was unlocked successfully, `false` if the + * account was already unlocked. Throws an error if the account could not be + * unlocked. + */ + async evm_unlockUnknownAccount(address: string, duration: number = 0) { + return this.#wallet.unlockUnknownAccount(address.toLowerCase(), duration); + } + + /** + * Locks any unknown account. + * + * Note: accounts known to the `personal` namespace and accounts returned by + * `eth_accounts` cannot be locked using this method. + * + * @param address address the address of the account to lock + * @returns `true` if the account was locked successfully, `false` if the + * account was already locked. Throws an error if the account could not be + * locked. + */ + async evm_lockUnknownAccount(address: string) { + const lowerAddress = address.toLowerCase(); + // if this is a known account, don'we can't unlock it this way + if (this.#wallet.knownAccounts.has(lowerAddress)) { + throw new Error("cannot lock known/personal account"); + } + return this.#wallet.lockAccount(lowerAddress); + } + + //#endregion evm + + //#region miner + /** + * Resume the CPU mining process with the given number of threads. + * + * Note: `threads` is ignored. + * @param threads + * @returns true + */ + @assertArgLength(0, 1) + async miner_start(threads: number = 1) { + if (this.#options.miner.legacyInstamine === true) { + const transactions = await this.#blockchain.resume(threads); + if (transactions != null && this.#options.chain.vmErrorsOnRPCResponse) { + assertExceptionalTransactions(transactions); + } + } else { + this.#blockchain.resume(threads); + } + return true; + } + + /** + * Stop the CPU mining operation. + */ + @assertArgLength(0) + async miner_stop() { + this.#blockchain.pause(); + return true; + } + + /** + * + * @param number Sets the minimal accepted gas price when mining transactions. + * Any transactions that are below this limit are excluded from the mining + * process. + */ + @assertArgLength(1) + async miner_setGasPrice(number: string) { + this.#options.miner.gasPrice = Quantity.from(number); + return true; + } + + /** + * Sets the etherbase, where mining rewards will go. + * @param address + */ + @assertArgLength(1) + async miner_setEtherbase(address: string) { + this.#blockchain.coinbase = Address.from(address); + return true; + } + + /** + * Set the extraData block header field a miner can include + * @param extra + */ + @assertArgLength(1) + async miner_setExtra(extra: string) { + const bytes = Data.from(extra); + const length = bytes.toBuffer().length; + if (length > 32) { + throw new Error(`extra exceeds max length. ${length} > 32`); + } + this.#options.miner.extraData = bytes; + return true; + } + //#endregion + + //#region web3 + /** + * Returns the current client version. + * @returns The current client version. + */ + @assertArgLength(0) + async web3_clientVersion() { + return CLIENT_VERSION; + } + + /** + * Returns Keccak-256 (not the standardized SHA3-256) of the given data. + * @param {data} the data to convert into a SHA3 hash. + * @returns The SHA3 result of the given string. + */ + @assertArgLength(1) + async web3_sha3(data: string) { + return Data.from(keccak("keccak256").update(data).digest()); + } + //#endregion + + //#region net + /** + * Returns the current network id. + * @returns The current network id. This value should NOT be JSON-RPC + * Quantity/Data encoded. + */ + @assertArgLength(0) + async net_version() { + return this.#options.chain.networkId.toString(); + } + + /** + * Returns `true` if client is actively listening for network connections. + * @returns `true` when listening, otherwise `false`. + */ + @assertArgLength(0) + async net_listening() { + return true; + } + + /** + * Returns number of peers currently connected to the client. + * @returns integer of the number of connected peers. + */ + @assertArgLength(0) + async net_peerCount() { + return RPCQUANTITY_ZERO; + } + //#endregion + + //#region eth + + /** + * Generates and returns an estimate of how much gas is necessary to allow the + * transaction to complete. The transaction will not be added to the + * blockchain. Note that the estimate may be significantly more than the + * amount of gas actually used by the transaction, for a variety of reasons + * including EVM mechanics and node performance. + * + * @returns the amount of gas used. + */ + @assertArgLength(1, 2) + async eth_estimateGas( + transaction: any, + blockNumber: Buffer | Tag | string = Tag.LATEST + ) { + const blockchain = this.#blockchain; + const blocks = blockchain.blocks; + const parentBlock = await blocks.get(blockNumber); + const parentHeader = parentBlock.header; + const options = this.#options; + + const generateVM = () => { + return blockchain.vm.copy(); + }; + return new Promise((resolve, reject) => { + const { coinbase } = blockchain; + const tx = Transaction.fromJSON( + transaction, + this.#common, + Transaction.types.fake + ); + if (tx._from == null) { + tx._from = coinbase.toBuffer(); + } + if (tx.gasLimit.length !== 0) { + tx.gas = tx.gasLimit; + } else { + if (tx.gas.length !== 0) { + tx.gasLimit = tx.gas; + } else { + // eth_estimateGas isn't subject to regular transaction gas limits + tx.gas = tx.gasLimit = options.miner.callGasLimit.toBuffer(); + } + } + const newBlock = new RuntimeBlock( + parentHeader.number, + parentHeader.parentHash, + parentHeader.miner, + tx.gas, + parentHeader.timestamp + ); + const runArgs = { + tx: tx, + block: newBlock, + skipBalance: true, + skipNonce: true + }; + estimateGas(generateVM, runArgs, (err: Error, result: any) => { + if (err) return reject(err); + resolve(Quantity.from(result.gasEstimate.toBuffer())); + }); + }); + // return GasEstimator.binSearch(blockchain, tx, blockNumber); + } + + /** + * Returns the current ethereum protocol version. + * @returns The current ethereum protocol version. + */ + @assertArgLength(0) + async eth_protocolVersion() { + return PROTOCOL_VERSION; + } + + /** + * Returns an object with data about the sync status or false. + * @returns An object with sync status data or false, when not syncing: + * startingBlock: {bigint} - The block at which the import started (will + * only be reset, after the sync reached his head) + * currentBlock: {bigint} - The current block, same as eth_blockNumber + * highestBlock: {bigint} - The estimated highest block + */ + @assertArgLength(0) + async eth_syncing() { + return false; + } + + /** + * Returns the client coinbase address. + * @returns 20 bytes - the current coinbase address. + */ + @assertArgLength(0) + async eth_coinbase() { + return this.#blockchain.coinbase; + } + + /** + * Returns information about a block by block number. + * @param number QUANTITY|TAG - integer of a block number, or the string "earliest", "latest" or "pending", as in the + * default block parameter. + * @param transactions Boolean - If true it returns the full transaction objects, if false only the hashes of the + * transactions. + * @returns the block, `null` if the block doesn't exist. + */ + @assertArgLength(1, 2) + async eth_getBlockByNumber(number: string | Buffer, transactions = false) { + const block = await this.#blockchain.blocks.get(number).catch(_ => null); + return block ? block.toJSON(transactions) : null; + } + + /** + * Returns information about a block by block hash. + * @param number QUANTITY|TAG - integer of a block number, or the string "earliest", "latest" or "pending", as in the + * default block parameter. + * @param transactions Boolean - If true it returns the full transaction objects, if false only the hashes of the + * transactions. + * @returns Block + */ + @assertArgLength(1, 2) + async eth_getBlockByHash(hash: string | Buffer, transactions = false) { + const block = await this.#blockchain.blocks + .getByHash(hash) + .catch(_ => null); + return block ? block.toJSON(transactions) : null; + } + + /** + * Returns the number of transactions in a block from a block matching the given block number. + * @param number QUANTITY|TAG - integer of a block number, or the string "earliest", "latest" or "pending", as in the + * default block parameter. + */ + @assertArgLength(1) + async eth_getBlockTransactionCountByNumber(number: string | Buffer) { + const rawBlock = await this.#blockchain.blocks.getRaw(number); + if (rawBlock) { + const data = rlpDecode(rawBlock); + return Quantity.from((data[1] as any).length); + } else { + return null; + } + } + + /** + * Returns the number of transactions in a block from a block matching the given block hash. + * @param hash DATA, 32 Bytes - hash of a block. + */ + @assertArgLength(1) + async eth_getBlockTransactionCountByHash(hash: string | Buffer) { + const number = await this.#blockchain.blocks.getNumberFromHash(hash); + if (number) { + return this.eth_getBlockTransactionCountByNumber(number); + } else { + return null; + } + } + + @assertArgLength(0) + async eth_getCompilers() { + return [] as string[]; + } + + /** + * Returns information about a transaction by block hash and transaction index position. + * @param hash DATA, 32 Bytes - hash of a block. + * @param index QUANTITY - integer of the transaction index position. + */ + @assertArgLength(2) + async eth_getTransactionByBlockHashAndIndex( + hash: string | Buffer, + index: string + ) { + const block = await this.eth_getBlockByHash(hash, true); + if (block) { + const tx = block.transactions[parseInt(index, 10)]; + if (tx) return tx; + } + return null; + } + + /** + * Returns information about a transaction by block number and transaction index position. + * @param number QUANTITY|TAG - a block number, or the string "earliest", "latest" or "pending", as in the default + * block parameter. + * @param index QUANTITY - integer of the transaction index position. + */ + @assertArgLength(2) + async eth_getTransactionByBlockNumberAndIndex( + number: string | Buffer, + index: string + ) { + const block = await this.eth_getBlockByNumber(number, true); + return block.transactions[parseInt(index, 10)]; + } + + /** + * Returns the number of uncles in a block from a block matching the given block hash. + * @param hash DATA, 32 Bytes - hash of a block. + */ + @assertArgLength(1) + async eth_getUncleCountByBlockHash(hash: string | Buffer) { + return RPCQUANTITY_ZERO; + } + + /** + * Returns the number of uncles in a block from a block matching the given block hash. + * @param hash DATA, 32 Bytes - hash of a block. + */ + @assertArgLength(1) + async eth_getUncleCountByBlockNumber(number: string | Buffer) { + return RPCQUANTITY_ZERO; + } + + /** + * Returns information about a uncle of a block by hash and uncle index position. + * + * @param hash - hash of a block + * @param index - the uncle's index position. + */ + @assertArgLength(2) + async eth_getUncleByBlockHashAndIndex(hash: Data, index: Quantity) { + return null as ReturnType; + } + + /** + * Returns information about a uncle of a block by hash and uncle index position. + * + * @param blockNumber - a block number, or the string "earliest", "latest" or "pending", as in the default block + * parameter. + * @param uncleIndex - the uncle's index position. + */ + @assertArgLength(2) + async eth_getUncleByBlockNumberAndIndex( + blockNumber: Buffer | Tag, + uncleIndex: Quantity + ) { + return null as ReturnType; + } + + /** + * Returns: An Array with the following elements + * 1: DATA, 32 Bytes - current block header pow-hash + * 2: DATA, 32 Bytes - the seed hash used for the DAG. + * 3: DATA, 32 Bytes - the boundary condition ("target"), 2^256 / difficulty. + * + * @param {QUANTITY} filterId - A filter id + * @returns the hash of the current block, the seedHash, and the boundary condition to be met ("target"). + */ + @assertArgLength(1) + async eth_getWork(filterId: Quantity) { + return [] as [string, string, string] | []; + } + + /** + * Used for submitting a proof-of-work solution + * + * @param {DATA, 8 Bytes} nonce - The nonce found (64 bits) + * @param {DATA, 32 Bytes} powHash - The header's pow-hash (256 bits) + * @param {DATA, 32 Bytes} digest - The mix digest (256 bits) + * @returns `true` if the provided solution is valid, otherwise `false`. + */ + @assertArgLength(3) + async eth_submitWork(nonce: Data, powHash: Data, digest: Data) { + return false; + } + + /** + * Used for submitting mining hashrate. + * + * @param {String} hashRate - a hexadecimal string representation (32 bytes) of the hash rate + * @param {String} clientID - A random hexadecimal(32 bytes) ID identifying the client + * @returns `true` if submitting went through succesfully and `false` otherwise. + */ + @assertArgLength(2) + async eth_submitHashrate(hashRate: string, clientID: string) { + return false; + } + + /** + * Returns `true` if client is actively mining new blocks. + * @returns returns `true` if the client is mining, otherwise `false`. + */ + @assertArgLength(0) + async eth_mining() { + // we return the blockchain's started state + return this.#blockchain.isStarted(); + } + + /** + * Returns the number of hashes per second that the node is mining with. + * @returns number of hashes per second. + */ + @assertArgLength(0) + async eth_hashrate() { + return RPCQUANTITY_ZERO; + } + + /** + * Returns the current price per gas in wei. + * @returns integer of the current gas price in wei. + */ + @assertArgLength(0) + async eth_gasPrice() { + return this.#options.miner.gasPrice; + } + + /** + * Returns a list of addresses owned by client. + * @returns Array of 20 Bytes - addresses owned by the client. + */ + @assertArgLength(0) + async eth_accounts() { + return this.#wallet.addresses; + } + + /** + * Returns the number of most recent block. + * @returns integer of the current block number the client is on. + */ + @assertArgLength(0) + async eth_blockNumber() { + return this.#blockchain.blocks.latest.header.number; + } + + /** + * Returns the currently configured chain id, a value used in + * replay-protected transaction signing as introduced by EIP-155. + * @returns The chain id as a string. + * @EIP [155 – Simple replay attack protection](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) + * + * @example + * ```javascript + * await provider.send("eth_chainId"); + * ``` + */ + @assertArgLength(0) + async eth_chainId() { + return Quantity.from(this.#options.chain.chainId); + } + + /** + * Returns the balance of the account of given address. + * @param address 20 Bytes - address to check for balance. + * @param blockNumber integer block number, or the string "latest", "earliest" + * or "pending", see the default block parameter + */ + @assertArgLength(1, 2) + async eth_getBalance( + address: string, + blockNumber: Buffer | Tag = Tag.LATEST + ) { + return this.#blockchain.accounts.getBalance( + Address.from(address), + blockNumber + ); + } + + /** + * Returns code at a given address. + * + * @param address 20 Bytes - address + * @param blockNumber integer block number, or the string "latest", "earliest" or "pending", see the default block + * parameter + * @returns the code from the given address. + */ + @assertArgLength(1, 2) + async eth_getCode(address: Buffer, blockNumber: Buffer | Tag = Tag.LATEST) { + const blockchain = this.#blockchain; + const blockProm = blockchain.blocks.getRaw(blockNumber); + + const trie = blockchain.trie.copy(); + const getFromTrie = (address: Buffer): Promise => + new Promise((resolve, reject) => { + trie.get(address, (err, data) => { + if (err) return void reject(err); + resolve(data); + }); + }); + const block = await blockProm; + if (!block) throw new Error("header not found"); + + const blockData = (rlpDecode(block) as unknown) as [ + [Buffer, Buffer, Buffer, Buffer /* stateRoot */] /* header */, + Buffer[], + Buffer[] + ]; + const headerData = blockData[0]; + const blockStateRoot = headerData[3]; + trie.root = blockStateRoot; + + const addressDataPromise = getFromTrie(Address.from(address).toBuffer()); + + const addressData = await addressDataPromise; + // An address's codeHash is stored in the 4th rlp entry + const codeHash = ((rlpDecode(addressData) as any) as [ + Buffer /*nonce*/, + Buffer /*amount*/, + Buffer /*stateRoot*/, + Buffer /*codeHash*/ + ])[3]; + // if this address isn't a contract, return 0x + if (!codeHash || KECCAK256_NULL.equals(codeHash)) { + return Data.from("0x"); + } + return new Promise((resolve, reject) => { + trie.getRaw(codeHash, (err, data) => { + if (err) return void reject(err); + resolve(Data.from(data)); + }); + }); + } + + /** + * Returns the value from a storage position at a given address. + * @param data 20 Bytes - address of the storage. + * @param quantity integer of the position in the storage. + * @param blockNumber integer block number, or the string "latest", "earliest" + * or "pending", see the default block parameter + */ + @assertArgLength(2, 3) + async eth_getStorageAt( + address: string, + position: bigint | number, + blockNumber: string | Buffer | Tag = Tag.LATEST + ) { + const blockProm = this.#blockchain.blocks.getRaw(blockNumber); + + const trie = this.#blockchain.trie.copy(); + const getFromTrie = (address: Buffer): Promise => + new Promise((resolve, reject) => { + trie.get(address, (err, data) => { + if (err) return void reject(err); + resolve(data); + }); + }); + const block = await blockProm; + if (!block) throw new Error("header not found"); + + const blockData = (rlpDecode(block) as unknown) as [ + [Buffer, Buffer, Buffer, Buffer /* stateRoot */] /* header */, + Buffer[], + Buffer[] + ]; + const headerData = blockData[0]; + const blockStateRoot = headerData[3]; + trie.root = blockStateRoot; + + const addressDataPromise = getFromTrie(Address.from(address).toBuffer()); + + const posBuff = Quantity.from(position).toBuffer(); + const length = posBuff.length; + let paddedPosBuff: Buffer; + if (length < 32) { + // storage locations are 32 bytes wide, so we need to expand any value + // given to 32 bytes. + paddedPosBuff = Buffer.allocUnsafe(32).fill(0); + posBuff.copy(paddedPosBuff, 32 - length); + } else if (length === 32) { + paddedPosBuff = posBuff; + } else { + // if the position value we're passed is > 32 bytes, truncate it. This is + // what geth does. + paddedPosBuff = posBuff.slice(-32); + } + + const addressData = await addressDataPromise; + // An address's stateRoot is stored in the 3rd rlp entry + trie.root = ((rlpDecode(addressData) as any) as [ + Buffer /*nonce*/, + Buffer /*amount*/, + Buffer /*stateRoot*/, + Buffer /*codeHash*/ + ])[2]; + const value = await getFromTrie(paddedPosBuff); + return Data.from(value); + } + + /** + * Returns the information about a transaction requested by transaction hash. + * + * @param transactionHash 32 Bytes - hash of a transaction + */ + @assertArgLength(1) + async eth_getTransactionByHash(transactionHash: string) { + const { transactions } = this.#blockchain; + const hashBuffer = Data.from(transactionHash).toBuffer(); + + // we must check the database before checking the pending cache, because the + // cache is updated _after_ the transaction is already in the database, and + // the database contains block info whereas the pending cache doesn't. + const transaction = await transactions.get(hashBuffer); + + if (transaction === null) { + // if we can't find it in the list of pending transactions, check the db! + const tx = transactions.transactionPool.find(hashBuffer); + return tx ? tx.toJSON(null) : null; + } else { + return transaction.toJSON(); + } + } + + /** + * Returns the receipt of a transaction by transaction hash. + * + * Note That the receipt is not available for pending transactions. + * + * @param transactionHash 32 Bytes - hash of a transaction + * @returns Returns the receipt of a transaction by transaction hash. + */ + @assertArgLength(1) + async eth_getTransactionReceipt(transactionHash: string) { + const { transactions, transactionReceipts, blocks } = this.#blockchain; + const txHash = Data.from(transactionHash).toBuffer(); + + const transactionPromise = transactions.get(txHash); + const receiptPromise = transactionReceipts.get(txHash); + const blockPromise = transactionPromise.then(t => + t ? blocks.get(t._blockNum) : null + ); + const [transaction, receipt, block] = await Promise.all([ + transactionPromise, + receiptPromise, + blockPromise + ]); + if (transaction) { + return receipt.toJSON(block, transaction); + } else { + return null; + } + } + + /** + * Creates new message call transaction or a contract creation, if the data field contains code. + * @param transaction + * @returns The transaction hash + */ + @assertArgLength(1) + async eth_sendTransaction(transaction: any) { + let fromString = transaction.from; + let from: Address; + if (fromString) { + from = Address.from(transaction.from); + fromString = from.toString().toLowerCase(); + } + + if (fromString == null) { + throw new Error("from not found; is required"); + } + + // Error checks. It's possible to JSON.stringify a Buffer to JSON. + // we actually now handle this "properly" (not sure about spec), but for + // legacy reasons we don't allow it. + if (transaction.to && typeof transaction.to !== "string") { + throw new Error("invalid to address"); + } + + const wallet = this.#wallet; + const isKnownAccount = wallet.knownAccounts.has(fromString); + const isUnlockedAccount = wallet.unlockedAccounts.has(fromString); + + if (!isUnlockedAccount) { + const msg = isKnownAccount + ? "authentication needed: password or unlock" + : "sender account not recognized"; + throw new Error(msg); + } + + const type = isKnownAccount + ? Transaction.types.none + : Transaction.types.fake; + + const tx = Transaction.fromJSON(transaction, this.#common, type); + if (tx.gasLimit.length === 0) { + tx.gasLimit = this.#options.miner.defaultTransactionGasLimit.toBuffer(); + } + + if (tx.gasPrice.length === 0) { + tx.gasPrice = this.#options.miner.gasPrice.toBuffer(); + } + + if (tx.value.length === 0) { + tx.value = Buffer.from([0]); + } + + if (tx.to.equals(utils.BUFFER_ZERO)) { + tx.to = utils.BUFFER_EMPTY; + } + + if (isUnlockedAccount) { + const secretKey = wallet.unlockedAccounts.get(fromString); + return this.#blockchain.queueTransaction(tx, secretKey); + } else { + return this.#blockchain.queueTransaction(tx); + } + } + + /** + * Creates new message call transaction or a contract creation for signed transactions. + * @param transaction + * @returns The transaction hash + */ + @assertArgLength(1) + async eth_sendRawTransaction(transaction: string) { + const tx = new Transaction( + transaction, + this.#common, + Transaction.types.signed + ); + return this.#blockchain.queueTransaction(tx); + } + + /** + * The sign method calculates an Ethereum specific signature with: + * `sign(keccak256("\x19Ethereum Signed Message:\n" + message.length + message)))`. + * + * By adding a prefix to the message makes the calculated signature + * recognizable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data + * (e.g. transaction) and use the signature to impersonate the victim. + * + * Note the address to sign with must be unlocked. + * + * @param account address + * @param data message to sign + * @returns Signature + */ + @assertArgLength(2) + async eth_sign(address: string | Buffer, message: string | Buffer) { + const account = Address.from(address).toString().toLowerCase(); + + const privateKey = this.#wallet.unlockedAccounts.get(account); + if (privateKey == null) { + throw new Error("cannot sign data; no private key"); + } + + const chainId = this.#options.chain.chainId; + const messageHash = hashPersonalMessage(Data.from(message).toBuffer()); + const { v, r, s } = ecsign(messageHash, privateKey.toBuffer(), chainId); + return toRpcSig(v, r, s, chainId); + } + + /** + * + * @param address Address of the account that will sign the messages. + * @param typedData Typed structured data to be signed. + * @returns Signature. As in `eth_sign`, it is a hex encoded 129 byte array + * starting with `0x`. It encodes the `r`, `s`, and `v` parameters from + * appendix F of the [yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf) + * in big-endian format. Bytes 0...64 contain the `r` parameter, bytes + * 64...128 the `s` parameter, and the last byte the `v` parameter. Note + * that the `v` parameter includes the chain id as specified in [EIP-155](https://eips.ethereum.org/EIPS/eip-155). + * @EIP [712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) + */ + @assertArgLength(2) + async eth_signTypedData(address: string | Buffer, typedData: TypedData) { + const account = Address.from(address).toString().toLowerCase(); + + const privateKey = this.#wallet.unlockedAccounts.get(account); + if (privateKey == null) { + throw new Error("cannot sign data; no private key"); + } + + if (!typedData.types) { + throw new Error("cannot sign data; types missing"); + } + + if (!typedData.types.EIP712Domain) { + throw new Error("cannot sign data; EIP712Domain definition missing"); + } + + if (!typedData.domain) { + throw new Error("cannot sign data; domain missing"); + } + + if (!typedData.primaryType) { + throw new Error("cannot sign data; primaryType missing"); + } + + if (!typedData.message) { + throw new Error("cannot sign data; message missing"); + } + + return signTypedData_v4(privateKey.toBuffer(), { data: typedData }); + } + + /** + * Starts a subscription to a particular event. For every event that matches + * the subscription a JSON-RPC notification with event details and + * subscription ID will be sent to a client. + * + * @param subscriptionName + * @returns A subscription id. + */ + eth_subscribe(subscriptionName: SubscriptionName): PromiEvent; + /** + * Starts a subscription to a particular event. For every event that matches + * the subscription a JSON-RPC notification with event details and + * subscription ID will be sent to a client. + * + * @param subscriptionName + * @param options Filter options: + * * `address`: either an address or an array of addresses. Only logs that + * are created from these addresses are returned + * * `topics`, only logs which match the specified topics + * @returns A subscription id. + */ + eth_subscribe( + subscriptionName: "logs", + options: BaseFilterArgs + ): PromiEvent; + @assertArgLength(1, 2) + eth_subscribe(subscriptionName: SubscriptionName, options?: BaseFilterArgs) { + const subscriptions = this.#subscriptions; + switch (subscriptionName) { + case "newHeads": { + const subscription = this.#getId(); + const promiEvent = PromiEvent.resolve(subscription); + + const unsubscribe = this.#blockchain.on("block", (block: Block) => { + const value = block; + const header = value.header; + const result = { + logsBloom: header.logsBloom, + miner: header.miner, + difficulty: header.difficulty, + extraData: header.extraData, + gasLimit: header.gasLimit, + gasUsed: header.gasUsed, + hash: block.hash(), + mixHash: block.header.mixHash, + nonce: header.nonce, + number: header.number, + parentHash: header.parentHash, + receiptsRoot: header.receiptsRoot, + stateRoot: header.stateRoot, + timestamp: header.timestamp, + transactionsRoot: header.transactionsRoot, + sha3Uncles: header.sha3Uncles + }; + + // TODO: move the JSON stringification closer to where the message + // is actually sent to the listener + promiEvent.emit("message", { + type: "eth_subscription", + data: { + result: JSON.parse(JSON.stringify(result)), + subscription: subscription.toString() + } + }); + }); + subscriptions.set(subscription.toString(), unsubscribe); + return promiEvent; + } + case "logs": { + const subscription = this.#getId(); + const promiEvent = PromiEvent.resolve(subscription); + + const { addresses, topics } = options + ? parseFilterDetails(options) + : { addresses: [], topics: [] }; + const unsubscribe = this.#blockchain.on( + "blockLogs", + (blockLogs: BlockLogs) => { + // TODO: move the JSON stringification closer to where the message + // is actually sent to the listener + const result = JSON.parse( + JSON.stringify([...blockLogs.filter(addresses, topics)]) + ); + promiEvent.emit("message", { + type: "eth_subscription", + data: { + result, + subscription: subscription.toString() + } + }); + } + ); + subscriptions.set(subscription.toString(), unsubscribe); + return promiEvent; + } + case "newPendingTransactions": { + const subscription = this.#getId(); + const promiEvent = PromiEvent.resolve(subscription); + + const unsubscribe = this.#blockchain.on( + "pendingTransaction", + (transaction: Transaction) => { + const result = Data.from(transaction.hash(), 32).toString(); + promiEvent.emit("message", { + type: "eth_subscription", + data: { + result, + subscription: subscription.toString() + } + }); + } + ); + subscriptions.set(subscription.toString(), unsubscribe); + return promiEvent; + } + case "syncing": { + // ganache doesn't sync, so doing nothing is perfectly valid. + const subscription = this.#getId(); + const promiEvent = PromiEvent.resolve(subscription); + + this.#subscriptions.set(subscription.toString(), () => {}); + return promiEvent; + } + default: + throw new CodedError( + `no \"${subscriptionName}\" subscription in eth namespace`, + ErrorCodes.METHOD_NOT_FOUND + ); + } + } + + @assertArgLength(1) + async eth_unsubscribe(subscriptionId: SubscriptionId) { + const subscriptions = this.#subscriptions; + const unsubscribe = subscriptions.get(subscriptionId); + if (unsubscribe) { + subscriptions.delete(subscriptionId); + unsubscribe(); + return true; + } else { + return false; + } + } + + /** + * Creates a filter in the node, to notify when a new block arrives. To check + * if the state has changed, call `eth_getFilterChanges`. + * + * @returns A filter id. + */ + @assertArgLength(0) + async eth_newBlockFilter() { + const unsubscribe = this.#blockchain.on("block", (block: Block) => { + value.updates.push(block.hash()); + }); + const value = { + updates: [], + unsubscribe, + filter: null, + type: FilterTypes.block + }; + const filterId = this.#getId(); + this.#filters.set(filterId.toString(), value); + return filterId; + } + + /** + * Creates a filter in the node, to notify when new pending transactions + * arrive. To check if the state has changed, call `eth_getFilterChanges`. + * + * @returns A filter id. + */ + @assertArgLength(0) + async eth_newPendingTransactionFilter() { + const unsubscribe = this.#blockchain.on( + "pendingTransaction", + (transaction: Transaction) => { + value.updates.push(Data.from(transaction.hash(), 32)); + } + ); + const value = { + updates: [], + unsubscribe, + filter: null, + type: FilterTypes.pendingTransaction + }; + const filterId = this.#getId(); + this.#filters.set(filterId.toString(), value); + return filterId; + } + + /** + * Creates a filter object, based on filter options, to notify when the state + * changes (logs). To check if the state has changed, call + * `eth_getFilterChanges`. + * + * If the from `fromBlock` or `toBlock` option are equal to "latest" the + * filter continually append logs for whatever block is seen as latest at the + * time the block was mined, not just for the block that was "latest" when the + * filter was created. + * + * ### A note on specifying topic filters: + * Topics are order-dependent. A transaction with a log with topics [A, B] + * will be matched by the following topic filters: + * * `[]` “anything” + * * `[A]` “A in first position (and anything after)” + * * `[null, B]` “anything in first position AND B in second position (and + * anything after)” + * * `[A, B]` “A in first position AND B in second position (and anything + * after)” + * * `[[A, B], [A, B]]` “(A OR B) in first position AND (A OR B) in second + * position (and anything after)” + * + * @param filter The filter options + */ + @assertArgLength(0, 1) + async eth_newFilter(filter: RangeFilterArgs = {}) { + const blockchain = this.#blockchain; + const { addresses, topics } = parseFilterDetails(filter); + const unsubscribe = blockchain.on("blockLogs", (blockLogs: BlockLogs) => { + const blockNumber = blockLogs.blockNumber; + // everytime we get a blockLogs message we re-check what the filter's + // range is. We do this because "latest" isn't the latest block at the + // time the filter was set up, rather it is the actual latest *mined* + // block (that is: not pending) + const { fromBlock, toBlock } = parseFilterRange(filter, blockchain); + if (fromBlock <= blockNumber && toBlock >= blockNumber) { + value.updates.push(...blockLogs.filter(addresses, topics)); + } + }); + const value = { updates: [], unsubscribe, filter, type: FilterTypes.log }; + const filterId = this.#getId(); + this.#filters.set(filterId.toString(), value); + return filterId; + } + + /** + * Polling method for a filter, which returns an array of logs, block hashes, + * or transaction hashes, depending on the filter type, which occurred since + * last poll. + * + * @param filterId the filter id. + * @returns an array of logs, block hashes, or transaction hashes, depending + * on the filter type, which occurred since last poll. + */ + @assertArgLength(1) + async eth_getFilterChanges(filterId: string) { + const filter = this.#filters.get(filterId); + if (filter) { + const updates = filter.updates; + filter.updates = []; + return updates; + } else { + throw new Error("filter not found"); + } + } + + /** + * Uninstalls a filter with given id. Should always be called when watch is + * no longer needed. + * + * @param filterId the filter id. + * @returns `true` if the filter was successfully uninstalled, otherwise + * `false`. + */ + @assertArgLength(1) + async eth_uninstallFilter(filterId: string) { + const filter = this.#filters.get(filterId); + if (!filter) return false; + filter.unsubscribe(); + return this.#filters.delete(filterId); + } + + /** + * Returns an array of all logs matching filter with given id. + * + * @returns Array of log objects, or an empty array. + */ + @assertArgLength(1) + async eth_getFilterLogs(filterId: string) { + const filter = this.#filters.get(filterId); + if (filter && filter.type === FilterTypes.log) { + return this.eth_getLogs(filter.filter); + } else { + throw new Error("filter not found"); + } + } + + /** + * Returns an array of all logs matching a given filter object. + * + * @param filter The filter options + * @returns Array of log objects, or an empty array. + */ + @assertArgLength(1) + async eth_getLogs(filter: FilterArgs) { + const blockchain = this.#blockchain; + if ("blockHash" in filter) { + const { addresses, topics } = parseFilterDetails(filter); + const blockNumber = await blockchain.blocks.getNumberFromHash( + filter.blockHash + ); + if (!blockNumber) return []; + const blockLogs = blockchain.blockLogs; + const logs = await blockLogs.get(blockNumber); + return logs ? [...logs.filter(addresses, topics)] : []; + } else { + const { addresses, topics, fromBlock, toBlockNumber } = parseFilter( + filter, + blockchain + ); + + const blockLogs = blockchain.blockLogs; + const pendingLogsPromises: Promise[] = [ + blockLogs.get(fromBlock.toBuffer()) + ]; + + const fromBlockNumber = fromBlock.toNumber(); + // if we have a range of blocks to search, do that here: + if (fromBlockNumber !== toBlockNumber) { + // fetch all the blockLogs in-between `fromBlock` and `toBlock` (excluding + // from, because we already started fetching that one) + for (let i = fromBlockNumber + 1, l = toBlockNumber + 1; i < l; i++) { + pendingLogsPromises.push(blockLogs.get(Quantity.from(i).toBuffer())); + } + } + + // now filter and compute all the blocks' blockLogs (in block order) + return Promise.all(pendingLogsPromises).then(blockLogsRange => { + const filteredBlockLogs: ReturnType< + typeof BlockLogs["logToJSON"] + >[] = []; + blockLogsRange.forEach(blockLogs => { + // TODO(perf): this loops over all addresses for every block. + // Maybe make it loop only once? + if (blockLogs) + filteredBlockLogs.push(...blockLogs.filter(addresses, topics)); + }); + return filteredBlockLogs; + }); + } + } + + /** + * Returns the number of transactions sent from an address. + * + * @param address + * @param blockNumber integer block number, or the string "latest", "earliest" + * or "pending", see the default block parameter + * @returns integer of the number of transactions sent from this address. + */ + @assertArgLength(1, 2) + async eth_getTransactionCount( + address: string, + blockNumber: Buffer | Tag = Tag.LATEST + ) { + return this.#blockchain.accounts.getNonce( + Address.from(address), + blockNumber + ); + } + + /** + * Executes a new message call immediately without creating a transaction on the block chain. + * + * @param transaction + * @param blockNumber + * + * @returns the return value of executed contract. + */ + @assertArgLength(1, 2) + async eth_call( + transaction: any, + blockNumber: string | Buffer | Tag = Tag.LATEST + ) { + const blockchain = this.#blockchain; + const blocks = blockchain.blocks; + const parentBlock = await blocks.get(blockNumber); + const parentHeader = parentBlock.header; + const options = this.#options; + + let gas: Quantity; + if (typeof transaction.gasLimit === "undefined") { + if (typeof transaction.gas !== "undefined") { + gas = Quantity.from(transaction.gas); + } else { + // eth_call isn't subject to regular transaction gas limits by default + gas = options.miner.callGasLimit; + } + } else { + gas = Quantity.from(transaction.gasLimit); + } + + let data: Data; + if (typeof transaction.data === "undefined") { + if (typeof transaction.input === "undefined") { + data = Data.from(transaction.input); + } + } else { + data = Data.from(transaction.data); + } + + const block = new RuntimeBlock( + parentHeader.number, + parentHeader.parentHash, + blockchain.coinbase, + gas.toBuffer(), + parentHeader.timestamp + ); + + const simulatedTransaction = { + gas, + // if we don't have a from address, our caller sut be the configured coinbase address + from: + transaction.from == null + ? blockchain.coinbase + : Address.from(transaction.from), + to: transaction.to == null ? null : Address.from(transaction.to), + gasPrice: Quantity.from( + transaction.gasPrice == null ? 0 : transaction.gasPrice + ), + value: + transaction.value == null ? null : Quantity.from(transaction.value), + data, + block + }; + + return blockchain.simulateTransaction(simulatedTransaction, parentBlock); + } + //#endregion + + //#region personal + /** + * Returns all the Ethereum account addresses of all keys that have been + * added. + * @returns the Ethereum account addresses of all keys that have been added. + */ + @assertArgLength(0) + async personal_listAccounts() { + return this.#wallet.addresses; + } + + /** + * Generates a new account with private key. Returns the address of the new + * account. + * @param passphrase + * @returns The new account's address + */ + @assertArgLength(1) + async personal_newAccount(passphrase: string) { + if (typeof passphrase !== "string") { + throw new Error("missing value for required argument `passphrase`"); + } + + const wallet = this.#wallet; + const newAccount = wallet.createRandomAccount( + this.#options.wallet.mnemonic + ); + const address = newAccount.address; + const strAddress = address.toString(); + const encryptedKeyFile = await wallet.encrypt( + newAccount.privateKey, + passphrase + ); + wallet.encryptedKeyFiles.set(strAddress, encryptedKeyFile); + wallet.addresses.push(strAddress); + wallet.knownAccounts.add(strAddress); + return newAccount.address; + } + + /** + * Imports the given unencrypted private key (hex string) into the key store, encrypting it with the passphrase. + * + * @param rawKey + * @param passphrase + * @returnsReturns the address of the new account. + */ + @assertArgLength(2) + async personal_importRawKey(rawKey: string, passphrase: string) { + if (typeof passphrase !== "string") { + throw new Error("missing value for required argument `passphrase`"); + } + + const wallet = this.#wallet; + const newAccount = Wallet.createAccountFromPrivateKey(Data.from(rawKey)); + const address = newAccount.address; + const strAddress = address.toString(); + const encryptedKeyFile = await wallet.encrypt( + newAccount.privateKey, + passphrase + ); + wallet.encryptedKeyFiles.set(strAddress, encryptedKeyFile); + wallet.addresses.push(strAddress); + wallet.knownAccounts.add(strAddress); + return newAccount.address; + } + + /** + * Locks the account. The account can no longer be used to send transactions. + * @param address + */ + @assertArgLength(1) + async personal_lockAccount(address: string) { + return this.#wallet.lockAccount(address.toLowerCase()); + } + + /** + * Unlocks the account for use. + * + * The unencrypted key will be held in memory until the unlock duration + * expires. The unlock duration defaults to 300 seconds. An explicit duration + * of zero seconds unlocks the key until geth exits. + * + * The account can be used with eth_sign and eth_sendTransaction while it is + * unlocked. + * @param address 20 Bytes - The address of the account to unlock. + * @param passphrase Passphrase to unlock the account. + * @param duration (default: 300) Duration in seconds how long the account + * should remain unlocked for. Set to 0 to disable automatic locking. + * @returns true if it worked. Throws an error if it did not. + */ + @assertArgLength(2, 3) + async personal_unlockAccount( + address: string, + passphrase: string, + duration: number = 300 + ) { + return this.#wallet.unlockAccount( + address.toLowerCase(), + passphrase, + duration + ); + } + + /** + * Validate the given passphrase and submit transaction. + * + * The transaction is the same argument as for eth_sendTransaction and + * contains the from address. If the passphrase can be used to decrypt the + * private key belogging to tx.from the transaction is verified, signed and + * send onto the network. The account is not unlocked globally in the node + * and cannot be used in other RPC calls. + * + * @param txData + * @param passphrase + */ + @assertArgLength(2) + async personal_sendTransaction(transaction: any, passphrase: string) { + let fromString = transaction.from; + let from: Address; + if (fromString) { + from = Address.from(transaction.from); + fromString = from.toString().toLowerCase(); + } + + if (fromString == null) { + throw new Error("from not found; is required"); + } + + const wallet = this.#wallet; + const encryptedKeyFile = wallet.encryptedKeyFiles.get(fromString); + if (encryptedKeyFile === undefined) { + throw new Error("no key for given address or file"); + } + let tx: Transaction; + if (encryptedKeyFile !== null) { + const secretKey = await wallet.decrypt(encryptedKeyFile, passphrase); + + tx = new Transaction(transaction, this.#common); + tx.sign(secretKey); + } else { + tx = new Transaction(transaction, this.#common, Transaction.types.fake); + } + + return this.#blockchain.queueTransaction(tx); + } + //#endregion + + //#region rpc + @assertArgLength(0) + async rpc_modules() { + return RPC_MODULES; + } + //endregion + + //#region shh + + /** + * Creates new whisper identity in the client. + * + * @returns {DATA, 60 Bytes} result - the address of the new identiy. + */ + @assertArgLength(0) + async shh_newIdentity() { + return "0x00"; + } + + /** + * Checks if the client hold the private keys for a given identity. + * + * @param {DATA, 60 Bytes} address - The identity address to check. + * @returns returns true if the client holds the privatekey for that identity, otherwise false. + */ + @assertArgLength(1) + async shh_hasIdentity(address: string) { + return false; + } + + /** + * Creates a new group. + * + * @returns the address of the new group. + */ + @assertArgLength(0) + async shh_newGroup() { + return "0x00"; + } + + /** + * Adds a whisper identity to the group + * + * @param {DATA, 60 Bytes} - The identity address to add to a group. + * @returns true if the identity was successfully added to the group, otherwise false. + */ + @assertArgLength(1) + async shh_addToGroup(address: string) { + return false; + } + + /** + * Creates filter to notify, when client receives whisper message matching the filter options. + * + * @param {DATA, 60 Bytes} to - + * ^(optional) Identity of the receiver. When present it will try to decrypt any incoming message + * if the client holds the private key to this identity. + * @param {Array of DATA} topics - Array of DATA topics which the incoming message's topics should match. + * @returns returns true if the identity was successfully added to the group, otherwise false. + */ + @assertArgLength(2) + async shh_newFilter(to: string, topics: any[]) { + return false; + } + + /** + * Uninstalls a filter with given id. Should always be called when watch is no longer needed. + * Additonally Filters timeout when they aren't requested with shh_getFilterChanges for a period of time. + * + * @param {QUANTITY} id - The filter id. Ex: "0x7" + * @returns true if the filter was successfully uninstalled, otherwise false. + */ + @assertArgLength(1) + async shh_uninstallFilter(id: string) { + return false; + } + + /** + * Polling method for whisper filters. Returns new messages since the last call of this method. + * + * @param {QUANTITY} id - The filter id. Ex: "0x7" + * @returns More Info: https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges + */ + @assertArgLength(1) + async shh_getFilterChanges(id: string) { + return []; + } + + /** + * Get all messages matching a filter. Unlike shh_getFilterChanges this returns all messages. + * + * @param {QUANTITY} id - The filter id. Ex: "0x7" + * @returns See: shh_getFilterChanges + */ + @assertArgLength(1) + async shh_getMessages(id: string) { + return false; + } + + /** + * Creates a whisper message and injects it into the network for distribution. + * + * @param postData + * @returns returns true if the message was sent, otherwise false. + */ + @assertArgLength(1) + async shh_post(postData: WhisperPostObject) { + return false; + } + + /** + * Returns the current whisper protocol version. + * + * @returns The current whisper protocol version + */ + @assertArgLength(0) + async shh_version() { + return "2"; + } + //#endregion +} diff --git a/src/chains/ethereum/src/blockchain.ts b/src/chains/ethereum/src/blockchain.ts new file mode 100644 index 0000000000..57aded2c45 --- /dev/null +++ b/src/chains/ethereum/src/blockchain.ts @@ -0,0 +1,821 @@ +import { EOL } from "os"; +import RuntimeError, { RETURN_TYPES } from "./errors/runtime-error"; +import Miner from "./miner/miner"; +import Database from "./database"; +import Emittery from "emittery"; +import BlockManager from "./data-managers/block-manager"; +import BlockLogs from "./things/blocklogs"; +import TransactionManager from "./data-managers/transaction-manager"; +import CheckpointTrie from "merkle-patricia-tree"; +import { BN, KECCAK256_RLP } from "ethereumjs-util"; +import Account from "./things/account"; +import { promisify } from "util"; +import { Quantity, Data } from "@ganache/utils"; +import EthereumJsAccount from "ethereumjs-account"; +import AccountManager from "./data-managers/account-manager"; +import { utils } from "@ganache/utils"; +import Transaction from "./things/transaction"; +import Manager from "./data-managers/manager"; +import TransactionReceipt from "./things/transaction-receipt"; +import { encode as rlpEncode } from "rlp"; +import Common from "ethereumjs-common"; +import VM from "ethereumjs-vm"; +import Address from "./things/address"; +import BlockLogManager from "./data-managers/blocklog-manager"; +import { EVMResult } from "ethereumjs-vm/dist/evm/evm"; +import { VmError, ERROR } from "ethereumjs-vm/dist/exceptions"; +import { EthereumInternalOptions } from "./options"; +import { Snapshots } from "./types/snapshots"; +import { RuntimeBlock, Block } from "./things/runtime-block"; +const { + BUFFER_EMPTY, + RPCQUANTITY_EMPTY, + BUFFER_32_ZERO, + BUFFER_256_ZERO, + RPCQUANTITY_ZERO +} = utils; + +type SimulationTransaction = { + /** + * The address the transaction is sent from. + */ + from: Address; + /** + * The address the transaction is directed to. + */ + to?: Address; + /** + * Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions. + */ + gas: Quantity; + /** + * Integer of the gasPrice used for each paid gas + */ + gasPrice: Quantity; + /** + * Integer of the value sent with this transaction + */ + value?: Quantity; + /** + * Hash of the method signature and encoded parameters. For details see Ethereum Contract ABI in the Solidity documentation + */ + data?: Data; + block: RuntimeBlock; +}; + +const unref = utils.unref; + +export enum Status { + // Flags + started = 1, // 0000 0001 + starting = 2, // 0000 0010 + stopped = 4, // 0000 0100 + stopping = 8, // 0000 1000 + paused = 16 // 0001 0000 +} + +type BlockchainTypedEvents = { + block: Block; + blockLogs: BlockLogs; + pendingTransaction: Transaction; +}; +type BlockchainEvents = "start" | "stop"; + +/** + * Sets the provided VM state manager's state root *without* first + * checking for checkpoints or flushing the existing cache. + * + * Useful if you know the state manager is not in a checkpoint and its internal + * cache is safe to discard. + * + * @param stateManager + * @param stateRoot + */ +function setStateRootSync(stateManager: VM["stateManager"], stateRoot: Buffer) { + stateManager._trie.root = stateRoot; + stateManager._cache.clear(); + stateManager._storageTries = {}; +} + +export default class Blockchain extends Emittery.Typed< + BlockchainTypedEvents, + BlockchainEvents +> { + #state: Status = Status.starting; + #miner: Miner; + #blockBeingSavedPromise: Promise<{ block: Block; blockLogs: BlockLogs }>; + public blocks: BlockManager; + public blockLogs: BlockLogManager; + public transactions: TransactionManager; + public transactionReceipts: Manager; + public accounts: AccountManager; + public vm: VM; + public trie: CheckpointTrie; + + readonly #database: Database; + readonly #common: Common; + readonly #options: EthereumInternalOptions; + readonly #instamine: boolean; + + /** + * Initializes the underlying Database and handles synchronization between + * the API and the database. + * + * Emits a `ready` event once the database and all dependencies are fully + * initialized. + * @param options + */ + constructor( + options: EthereumInternalOptions, + common: Common, + initialAccounts: Account[], + coinbaseAddress: Address + ) { + super(); + this.#options = options; + this.#common = common; + + const instamine = (this.#instamine = + !options.miner.blockTime || options.miner.blockTime <= 0); + const legacyInstamine = options.miner.legacyInstamine; + + { + // warnings and errors + if (legacyInstamine) { + console.info( + "Legacy instamining, where transactions are fully mined before the hash is returned, is deprecated and will be removed in the future." + ); + } + + if (!instamine) { + if (legacyInstamine) { + console.info( + "Setting `legacyInstamine` to `true` has no effect when blockTime is non-zero" + ); + } + + if (options.chain.vmErrorsOnRPCResponse) { + console.info( + "Setting `vmErrorsOnRPCResponse` to `true` has no effect on transactions when blockTime is non-zero" + ); + } + } + } + + const database = (this.#database = new Database(options.database, this)); + database.once("ready").then(async () => { + const blocks = (this.blocks = await BlockManager.initialize( + common, + database.blockIndexes, + database.blocks + )); + + // if we have a latest block, use it to set up the trie. + const latest = blocks.latest; + if (latest) { + this.#blockBeingSavedPromise = Promise.resolve({ + block: latest, + blockLogs: null + }); + this.trie = new CheckpointTrie( + database.trie, + latest.header.stateRoot.toBuffer() + ); + } else { + this.trie = new CheckpointTrie(database.trie, null); + } + + this.blockLogs = new BlockLogManager(database.blockLogs); + this.transactions = new TransactionManager( + options.miner, + common, + this, + database.transactions + ); + this.transactionReceipts = new Manager( + database.transactionReceipts, + TransactionReceipt + ); + this.accounts = new AccountManager(this, database.trie); + + this.coinbase = coinbaseAddress; + + // create VM and listen to step events + this.vm = this.createVmFromStateTrie( + this.trie, + options.chain.allowUnlimitedContractSize + ); + + await this.#commitAccounts(initialAccounts); + + { + // create first block + let firstBlockTime: number; + if (options.chain.time != null) { + // If we were given a timestamp, use it instead of the `_currentTime` + const t = +options.chain.time; + firstBlockTime = Math.floor(t / 1000); + this.setTime(t); + } else { + firstBlockTime = this.#currentTime(); + } + + // if we don't already have a latest block, create a genesis block! + if (!latest) { + this.#blockBeingSavedPromise = this.#initializeGenesisBlock( + firstBlockTime, + options.miner.blockGasLimit + ); + blocks.earliest = blocks.latest = await this.#blockBeingSavedPromise.then( + ({ block }) => block + ); + } + } + + { + // configure and start miner + const txPool = this.transactions.transactionPool; + const minerOpts = options.miner; + const miner = (this.#miner = new Miner( + minerOpts, + txPool.executables, + instamine, + this.vm, + this.#readyNextBlock + )); + + //#region automatic mining + const nullResolved = Promise.resolve(null); + const mineAll = (maxTransactions: number) => + this.#isPaused() ? nullResolved : this.mine(maxTransactions); + if (instamine) { + // insta mining + // whenever the transaction pool is drained mine the txs into blocks + txPool.on("drain", mineAll.bind(null, 1)); + } else { + // interval mining + const wait = () => unref(setTimeout(next, minerOpts.blockTime * 1e3)); + const next = () => mineAll(-1).then(wait); + wait(); + } + //#endregion + + miner.on("block", this.#handleNewBlockData); + + this.once("stop").then(() => miner.clearListeners()); + } + + this.#state = Status.started; + this.emit("start"); + }); + } + + #saveNewBlock = ({ + block, + serialized + }: { + block: Block; + serialized: Buffer; + }) => { + const { blocks } = this; + blocks.latest = block; + return this.#database.batch(() => { + const blockHash = block.hash().toBuffer(); + const blockHeader = block.header; + const blockNumberQ = blockHeader.number; + const blockNumber = blockHeader.number.toBuffer(); + const blockLogs = BlockLogs.create(blockHash); + const timestamp = new Date( + blockHeader.timestamp.toNumber() * 1000 + ).toString(); + const logOutput: string[] = []; + block.getTransactions().forEach((tx: Transaction, i: number) => { + const hash = tx.hash(); + const index = Quantity.from(i).toBuffer(); + const txAndExtraData = [ + ...tx.raw, + blockHash, + blockNumber, + index, + Buffer.from([tx.type]), + tx.from + ]; + const encodedTx = rlpEncode(txAndExtraData); + this.transactions.set(hash, encodedTx); + + const receipt = tx.getReceipt(); + const encodedReceipt = receipt.serialize(true); + this.transactionReceipts.set(hash, encodedReceipt); + + tx.getLogs().forEach(blockLogs.append.bind(blockLogs, index, hash)); + + logOutput.push( + this.#getTransactionLogOutput( + hash, + receipt, + blockNumberQ, + timestamp, + tx.execException + ) + ); + }); + + blockLogs.blockNumber = blockNumberQ; + this.blockLogs.set(blockNumber, blockLogs.serialize()); + blocks.putBlock(blockNumber, blockHash, serialized); + this.#options.logging.logger.log(logOutput.join(EOL)); + return { block, blockLogs }; + }); + }; + + #emitNewBlock = async (blockInfo: { block: Block; blockLogs: BlockLogs }) => { + const options = this.#options; + const { block, blockLogs } = blockInfo; + + // emit the block once everything has been fully saved to the database + block.getTransactions().forEach(transaction => { + transaction.finalize("confirmed", transaction.execException); + }); + + if (this.#instamine && options.miner.legacyInstamine) { + // in legacy instamine mode we must delay the broadcast of new blocks + await new Promise(resolve => { + process.nextTick(async () => { + // emit block logs first so filters can pick them up before + // block listeners are notified + await Promise.all([ + this.emit("blockLogs", blockLogs), + this.emit("block", block) + ]); + resolve(void 0); + }); + }); + } else { + // emit block logs first so filters can pick them up before + // block listeners are notified + await Promise.all([ + this.emit("blockLogs", blockLogs), + this.emit("block", block) + ]); + } + + return blockInfo; + }; + + #getTransactionLogOutput = ( + hash: Buffer, + receipt: TransactionReceipt, + blockNumber: Quantity, + timestamp: string, + error: RuntimeError | undefined + ) => { + let str = `${EOL} Transaction: ${Data.from(hash)}${EOL}`; + + const contractAddress = receipt.contractAddress; + if (contractAddress != null) { + str += ` Contract created: ${Address.from(contractAddress)}${EOL}`; + } + + str += ` Gas usage: ${Quantity.from(receipt.raw[1]).toNumber()}${EOL} + Block number: ${blockNumber.toNumber()}${EOL} + Block time: ${timestamp}${EOL}`; + + if (error) { + str += ` Runtime error: ${error.data.message}${EOL}`; + if (error.data.reason) { + str += ` Revert reason: ${error.data.reason}${EOL}`; + } + } + + return str; + }; + + #handleNewBlockData = async (blockData: { + block: Block; + serialized: Buffer; + }) => { + this.#blockBeingSavedPromise = this.#blockBeingSavedPromise + .then(() => this.#saveNewBlock(blockData)) + .then(this.#emitNewBlock); + + return this.#blockBeingSavedPromise; + }; + + coinbase: Address; + + #readyNextBlock = (previousBlock: Block, timestamp?: number) => { + const previousHeader = previousBlock.header; + const previousNumber = previousHeader.number.toBigInt() || 0n; + return new RuntimeBlock( + Quantity.from(previousNumber + 1n), + previousBlock.hash(), + this.coinbase, + this.#options.miner.blockGasLimit.toBuffer(), + Quantity.from(timestamp == null ? this.#currentTime() : timestamp) + ); + }; + + isStarted = () => { + return this.#state === Status.started; + }; + + mine = async ( + maxTransactions: number, + timestamp?: number, + onlyOneBlock: boolean = false + ) => { + await this.#blockBeingSavedPromise; + const nextBlock = this.#readyNextBlock(this.blocks.latest, timestamp); + return this.#miner.mine(nextBlock, maxTransactions, onlyOneBlock); + }; + + #isPaused = () => { + return (this.#state & Status.paused) !== 0; + }; + + pause() { + this.#state |= Status.paused; + } + + resume(_threads: number = 1) { + if (!this.#isPaused()) { + console.log("Warning: startMining called when miner was already started"); + return; + } + + // toggles the `paused` bit + this.#state ^= Status.paused; + + // if we are instamining mine a block right away + if (this.#instamine) { + return this.mine(-1); + } + } + + createVmFromStateTrie = ( + stateTrie: CheckpointTrie, + allowUnlimitedContractSize: boolean + ) => { + const blocks = this.blocks; + // ethereumjs vm doesn't use the callback style anymore + const getBlock = class T { + static async [promisify.custom](number: BN) { + const block = await blocks.get(number.toBuffer()).catch(_ => null); + return block ? { hash: () => block.hash().toBuffer() } : null; + } + }; + + return new VM({ + state: stateTrie, + activatePrecompiles: true, + common: this.#common, + allowUnlimitedContractSize, + blockchain: { + getBlock + } as any + }); + }; + + #commitAccounts = async (accounts: Account[]): Promise => { + const stateManager = this.vm.stateManager; + const putAccount = promisify(stateManager.putAccount.bind(stateManager)); + const checkpoint = promisify(stateManager.checkpoint.bind(stateManager)); + const commit = promisify(stateManager.commit.bind(stateManager)); + await checkpoint(); + const l = accounts.length; + const pendingAccounts = Array(l); + for (let i = 0; i < l; i++) { + const account = accounts[i]; + const ethereumJsAccount = new EthereumJsAccount(); + (ethereumJsAccount.nonce = account.nonce.toBuffer()), + (ethereumJsAccount.balance = account.balance.toBuffer()); + pendingAccounts[i] = putAccount( + account.address.toBuffer(), + ethereumJsAccount + ); + } + await Promise.all(pendingAccounts); + await commit(); + }; + + #initializeGenesisBlock = async ( + timestamp: number, + blockGasLimit: Quantity + ) => { + // README: block `0` is weird in that a `0` _should_ be hashed as `[]`, + // but actually return a real `0` with read back later. So we pull some + // shenangians here so we don't require checks in functions that consume + // this block's `0` value later + const rawBlockNumber = RPCQUANTITY_EMPTY; + + // create the genesis block + const genesis = new RuntimeBlock( + rawBlockNumber, + Quantity.from(BUFFER_32_ZERO), + this.#options.miner.coinbase as Address, + blockGasLimit.toBuffer(), + Quantity.from(timestamp) + ); + + // store the genesis block in the database + const { block, serialized } = genesis.finalize( + KECCAK256_RLP, + KECCAK256_RLP, + BUFFER_256_ZERO, + this.trie.root, + BUFFER_EMPTY, + this.#options.miner.extraData, + [] + ); + // README: set the block number to an actual 0 now. + block.header.number = RPCQUANTITY_ZERO; + const hash = block.hash().toBuffer(); + return this.blocks + .putBlock(block.header.number.toBuffer(), hash, serialized) + .then(_ => ({ + block, + blockLogs: BlockLogs.create(hash) + })); + }; + + #timeAdjustment: number = 0; + + /** + * Returns the timestamp, adjusted by the timeAdjustent offset, in seconds. + */ + #currentTime = () => { + return Math.floor((Date.now() + this.#timeAdjustment) / 1000); + }; + + /** + * @param seconds + * @returns the total time offset *in milliseconds* + */ + public increaseTime(seconds: number) { + if (seconds < 0) { + seconds = 0; + } + return (this.#timeAdjustment += seconds); + } + + /** + * @param seconds + * @returns the total time offset *in milliseconds* + */ + public setTime(timestamp: number) { + return (this.#timeAdjustment = timestamp - Date.now()); + } + + #deleteBlockData = (blocksToDelete: Block[]) => { + return this.#database.batch(() => { + const { blocks, transactions, transactionReceipts, blockLogs } = this; + blocksToDelete.forEach(value => { + value.getTransactions().forEach(tx => { + const txHash = tx.hash(); + transactions.del(txHash); + transactionReceipts.del(txHash); + }); + const blockNum = value.header.number.toBuffer(); + blocks.del(blockNum); + blocks.del(value.hash().toBuffer()); + blockLogs.del(blockNum); + }); + }); + }; + + // TODO(stability): this.#snapshots is a potential unbound memory suck. Caller + // could call `evm_snapshot` over and over to grow the snapshot stack + // indefinitely. `this.#snapshots.blocks` is even worse. To solve this we + // might need to store in the db. An unlikely real problem, but possible. + #snapshots: Snapshots = { + snaps: [], + blocks: null, + unsubscribeFromBlocks: null + }; + + public snapshot() { + const snapshots = this.#snapshots; + const snaps = snapshots.snaps; + + // Subscription ids are based on the number of active snapshots. Weird? Yes. + // But it's the way it's been since the beginning so it just hasn't been + // changed. Feel free to change it so ids are unique if it bothers you + // enough. + const id = snaps.push({ + block: this.blocks.latest, + timeAdjustment: this.#timeAdjustment + }); + + // start listening to new blocks if this is the first snapshot + if (id === 1) { + snapshots.unsubscribeFromBlocks = this.on("block", block => { + snapshots.blocks = { + current: block.hash().toBuffer(), + next: snapshots.blocks + }; + }); + } + + this.#options.logging.logger.log("Saved snapshot #" + id); + + return id; + } + + public async revert(snapshotId: Quantity) { + const rawValue = snapshotId.valueOf(); + if (rawValue === null || rawValue === undefined) { + throw new Error("invalid snapshotId"); + } + + this.#options.logging.logger.log("Reverting to snapshot #" + snapshotId); + + // snapshot ids can't be < 1, so we do a quick sanity check here + if (rawValue < 1n) { + return false; + } + + const snapshots = this.#snapshots; + const snaps = snapshots.snaps; + const snapshotIndex = Number(rawValue - 1n); + const snapshot = snaps[snapshotIndex]; + + if (!snapshot) { + return false; + } + + // pause processing new transactions... + await this.transactions.pause(); + + // then pause the miner, too. + await this.#miner.pause(); + + // wait for anything in the process of being saved to finish up + await this.#blockBeingSavedPromise; + + // Pending transactions are always removed when you revert, even if they + // were present before the snapshot was created. Ideally, we'd remove only + // the new transactions.. but we'll leave that for another day. + this.transactions.clear(); + + const blocks = this.blocks; + const currentHash = blocks.latest.hash().toBuffer(); + const snapshotBlock = snapshot.block; + const snapshotHeader = snapshotBlock.header; + const snapshotHash = snapshotBlock.hash().toBuffer(); + + // remove this and all stored snapshots after this snapshot + snaps.splice(snapshotIndex); + + // if there are no more listeners, stop listening to new blocks + if (snaps.length === 0) { + snapshots.unsubscribeFromBlocks(); + } + + // if the snapshot's hash is different than the latest block's hash we've + // got new blocks to clean up. + if (!currentHash.equals(snapshotHash)) { + // if we've added blocks since we snapshotted we need to delete them and put + // some things back the way they were. + const blockPromises = []; + let blockList = snapshots.blocks; + while (blockList !== null) { + if (blockList.current.equals(snapshotHash)) break; + blockPromises.push(blocks.getByHash(blockList.current)); + blockList = blockList.next; + } + snapshots.blocks = blockList; + + await Promise.all(blockPromises).then(this.#deleteBlockData); + + setStateRootSync( + this.vm.stateManager, + snapshotHeader.stateRoot.toBuffer() + ); + blocks.latest = snapshotBlock; + } + + // put our time adjustment back + this.#timeAdjustment = snapshot.timeAdjustment; + + // resume mining + this.#miner.resume(); + + // resume processing transactions + this.transactions.resume(); + + return true; + } + + public async queueTransaction(transaction: Transaction, secretKey?: Data) { + // NOTE: this.transactions.add *must* be awaited before returning the + // `transaction.hash()`, as the transactionPool may change the transaction + // (and thus its hash!) + // It may also throw Errors that must be returned to the caller. + const isExecutable = + (await this.transactions.add(transaction, secretKey)) === true; + if (isExecutable) { + process.nextTick(this.emit.bind(this), "pendingTransaction", transaction); + } + + const hash = Data.from(transaction.hash(), 32); + if (this.#isPaused() || !this.#instamine) { + return hash; + } else { + if (this.#instamine && this.#options.miner.legacyInstamine) { + // in legacyInstamine mode we must wait for the transaction to be saved + // before we can return the hash + const { status, error } = await transaction.once("finalized"); + // in legacyInstamine mode we must throw on all rejected transaction + // errors. We must also throw on `confirmed` tranactions when + // vmErrorsOnRPCResposnse is enabled. + if ( + error && + (status === "rejected" || this.#options.chain.vmErrorsOnRPCResponse) + ) + throw error; + } + return hash; + } + } + + public async simulateTransaction( + transaction: SimulationTransaction, + parentBlock: Block + ) { + let result: EVMResult; + const options = this.#options; + + const data = transaction.data; + let gasLeft = transaction.gas.toBigInt(); + // subtract out the transaction's base fee from the gas limit before + // simulating the tx, because `runCall` doesn't account for raw gas costs. + gasLeft -= Transaction.calculateIntrinsicGas( + data ? data.toBuffer() : null, + options.chain.hardfork + ); + + if (gasLeft >= 0) { + const stateTrie = new CheckpointTrie( + this.#database.trie, + parentBlock.header.stateRoot.toBuffer() + ); + const vm = this.createVmFromStateTrie( + stateTrie, + this.vm.allowUnlimitedContractSize + ); + + result = await vm.runCall({ + caller: transaction.from.toBuffer(), + data: transaction.data && transaction.data.toBuffer(), + gasPrice: transaction.gasPrice.toBuffer(), + gasLimit: Quantity.from(gasLeft).toBuffer(), + to: transaction.to && transaction.to.toBuffer(), + value: transaction.value && transaction.value.toBuffer(), + block: transaction.block + }); + } else { + result = { + execResult: { + runState: { programCounter: 0 }, + exceptionError: new VmError(ERROR.OUT_OF_GAS), + returnValue: BUFFER_EMPTY + } + } as any; + } + if (result.execResult.exceptionError) { + if (this.#options.chain.vmErrorsOnRPCResponse) { + // eth_call transactions don't really have a transaction hash + const hash = BUFFER_EMPTY; + throw new RuntimeError(hash, result, RETURN_TYPES.RETURN_VALUE); + } else { + return Data.from(result.execResult.returnValue || "0x"); + } + } else { + return Data.from(result.execResult.returnValue || "0x"); + } + } + + /** + * Gracefully shuts down the blockchain service and all of its dependencies. + */ + public async stop() { + // If the blockchain is still initalizing we don't want to shut down + // yet because there may still be database calls in flight. Leveldb may + // cause a segfault due to a race condition between a db write and the close + // call. + if (this.#state === Status.starting) { + await this.once("start"); + } + + // clean up listeners + this.vm.removeAllListeners(); + this.transactions.transactionPool.clearListeners(); + await this.emit("stop"); + + if (this.#state === Status.started) { + this.#state = Status.stopping; + await this.#database.close(); + this.#state = Status.stopped; + } + } +} diff --git a/src/chains/ethereum/src/connector.ts b/src/chains/ethereum/src/connector.ts new file mode 100644 index 0000000000..0c8a3f14fc --- /dev/null +++ b/src/chains/ethereum/src/connector.ts @@ -0,0 +1,140 @@ +import Emittery from "emittery"; +import EthereumApi from "./api"; +import { JsonRpcTypes, types, utils } from "@ganache/utils"; +import EthereumProvider from "./provider"; +import { RecognizedString, WebSocket, HttpRequest } from "uWebSockets.js"; +import CodedError, { ErrorCodes } from "./errors/coded-error"; +import { EthereumProviderOptions, EthereumLegacyOptions } from "./options"; + +function isHttp( + connection: HttpRequest | WebSocket +): connection is HttpRequest { + return connection.constructor.name === "uWS.HttpRequest"; +} + +export type ProviderOptions = EthereumProviderOptions | EthereumLegacyOptions; +export type Provider = EthereumProvider; +export const Provider = EthereumProvider; +export const FlavorName = "ethereum" as const; + +export class Connector + extends Emittery.Typed + implements + types.Connector< + EthereumApi, + JsonRpcTypes.Request | JsonRpcTypes.Request[], + JsonRpcTypes.Response + > { + #provider: EthereumProvider; + + get provider() { + return this.#provider; + } + + constructor( + providerOptions: ProviderOptions = null, + executor: utils.Executor + ) { + super(); + + const provider = (this.#provider = new EthereumProvider( + providerOptions, + executor + )); + provider.on("connect", () => { + // tell the consumer (like a `ganache-core` server/connector) everything is ready + this.emit("ready"); + }); + } + + parse(message: Buffer) { + try { + return JSON.parse(message) as JsonRpcTypes.Request; + } catch (e) { + throw new CodedError(e.message, ErrorCodes.PARSE_ERROR); + } + } + + handle( + payload: + | JsonRpcTypes.Request + | JsonRpcTypes.Request[], + connection: HttpRequest | WebSocket + ) { + if (Array.isArray(payload)) { + // handle batch transactions + const promises = payload.map(payload => + this.#handle(payload, connection) + .then(({ value }) => value) + .catch(e => e) + ); + return Promise.resolve({ value: Promise.all(promises) }); + } else { + return this.#handle(payload, connection); + } + } + #handle = ( + payload: JsonRpcTypes.Request, + connection: HttpRequest | WebSocket + ) => { + const method = payload.method; + if (method === "eth_subscribe") { + if (isHttp(connection)) { + return Promise.reject( + new CodedError( + "notifications not supported", + ErrorCodes.METHOD_NOT_SUPPORTED + ) + ); + } + } + const params = payload.params as Parameters; + return this.#provider._requestRaw({ method, params }); + }; + + format( + result: any, + payload: JsonRpcTypes.Request + ): RecognizedString; + format( + results: any[], + payloads: JsonRpcTypes.Request[] + ): RecognizedString; + format( + results: any | any[], + payload: + | JsonRpcTypes.Request + | JsonRpcTypes.Request[] + ): RecognizedString { + if (Array.isArray(payload)) { + return JSON.stringify( + payload.map((payload, i) => { + const result = results[i]; + if (result instanceof Error) { + return JsonRpcTypes.Error(payload.id, result as any); + } else { + return JsonRpcTypes.Response(payload.id, result); + } + }) + ); + } else { + const json = JsonRpcTypes.Response(payload.id, results); + return JSON.stringify(json); + } + } + + formatError( + error: Error & { code: number }, + payload: JsonRpcTypes.Request + ): RecognizedString { + const json = JsonRpcTypes.Error( + payload && payload.id ? payload.id : null, + error + ); + return JSON.stringify(json); + } + + close() { + return this.#provider.disconnect(); + } +} diff --git a/src/chains/ethereum/src/data-managers/account-manager.ts b/src/chains/ethereum/src/data-managers/account-manager.ts new file mode 100644 index 0000000000..f0be2b9c37 --- /dev/null +++ b/src/chains/ethereum/src/data-managers/account-manager.ts @@ -0,0 +1,71 @@ +import Account from "../things/account"; +import Address from "../things/address"; +import Trie from "merkle-patricia-tree/baseTrie"; +import Blockchain from "../blockchain"; +import Tag from "../things/tags"; +import { LevelUp } from "levelup"; +import { rlp } from "ethereumjs-util"; +import { utils, Quantity } from "@ganache/utils"; + +const RPCQUANTITY_ZERO = utils.RPCQUANTITY_ZERO; + +export default class AccountManager { + #blockchain: Blockchain; + #trie: LevelUp; + constructor(blockchain: Blockchain, trie: LevelUp) { + this.#blockchain = blockchain; + this.#trie = trie; + } + + public async getRaw( + address: Address, + blockNumber: Buffer | Tag = Tag.LATEST + ): Promise { + const blockchain = this.#blockchain; + const block = await blockchain.blocks.get(blockNumber); + const trieCopy = new Trie(this.#trie, block.header.stateRoot.toBuffer()); + return new Promise((resolve, reject) => { + trieCopy.get(address.toBuffer(), (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); + } + + public async getNonce( + address: Address, + blockNumber: Buffer | Tag = Tag.LATEST + ): Promise { + return this.getRaw(address, blockNumber).then(data => { + if (data) { + const [nonce] = (rlp.decode(data) as any) as Buffer[]; + return nonce.length === 0 ? RPCQUANTITY_ZERO : Quantity.from(nonce); + } else { + return RPCQUANTITY_ZERO; + } + }); + } + + public async getBalance( + address: Address, + blockNumber: Buffer | Tag = Tag.LATEST + ): Promise { + return this.getRaw(address, blockNumber).then(data => { + if (data) { + const [, balance] = (rlp.decode(data) as any) as Buffer[]; + return balance.length === 0 ? RPCQUANTITY_ZERO : Quantity.from(balance); + } else { + return RPCQUANTITY_ZERO; + } + }); + } + + public async get( + address: Address, + blockNumber: Buffer | Tag = Tag.LATEST + ): Promise { + return this.getRaw(address, blockNumber).then(data => { + return Account.fromBuffer(data); + }); + } +} diff --git a/src/chains/ethereum/src/data-managers/block-manager.ts b/src/chains/ethereum/src/data-managers/block-manager.ts new file mode 100644 index 0000000000..c05bf9505b --- /dev/null +++ b/src/chains/ethereum/src/data-managers/block-manager.ts @@ -0,0 +1,153 @@ +import Manager from "./manager"; +import Tag from "../things/tags"; +import { LevelUp } from "levelup"; +import { Quantity, Data } from "@ganache/utils"; +import Common from "ethereumjs-common"; +import { Block } from "../things/runtime-block"; + +const NOTFOUND = 404; + +const EMPTY_BUFFER = Buffer.from([]); + +export default class BlockManager extends Manager { + /** + * The earliest block + */ + public earliest: Block; + + /** + * The latest block + */ + public latest: Block; + + /** + * The next block + */ + public pending: Block; + + #common: Common; + #blockIndexes: LevelUp; + + static async initialize( + common: Common, + blockIndexes: LevelUp, + base: LevelUp + ) { + const bm = new BlockManager(common, blockIndexes, base); + await bm.updateTaggedBlocks(); + return bm; + } + + constructor(common: Common, blockIndexes: LevelUp, base: LevelUp) { + super(base, Block, common); + + this.#common = common; + this.#blockIndexes = blockIndexes; + } + + getBlockByTag(tag: Tag) { + switch (Tag.normalize(tag as Tag)) { + case Tag.LATEST: + return this.latest; + case void 0: + case null: + // the key is probably a hex string, let nature takes its course. + break; + case Tag.PENDING: + // TODO: build a real pending block! + return this.latest; // this.createBlock(this.latest.header); + case Tag.EARLIEST: + return this.earliest; + default: + // this probably can't happen. but if someone passed something like + // `toString` in as a block tag and it got this far... maybe we'd + // get here... + throw new Error(`Invalid block Tag: ${tag}`); + } + } + + getEffectiveNumber(tagOrBlockNumber: string | Buffer | Tag = Tag.LATEST) { + if (typeof tagOrBlockNumber === "string") { + const block = this.getBlockByTag(tagOrBlockNumber as Tag); + if (block) { + return block.header.number; + } + } + return Quantity.from(tagOrBlockNumber); + } + + async getNumberFromHash(hash: string | Buffer | Tag) { + return this.#blockIndexes.get(Data.from(hash).toBuffer()).catch(e => { + if (e.status === NOTFOUND) return null; + throw e; + }) as Promise; + } + + async getByHash(hash: string | Buffer | Tag) { + const number = await this.getNumberFromHash(hash); + return number ? super.get(number) : null; + } + + async getRaw(tagOrBlockNumber: string | Buffer | Tag) { + // TODO(perf): make the block's raw fields accessible on latest/earliest/pending so + // we don't have to fetch them from the db each time a block tag is used. + return super.getRaw(this.getEffectiveNumber(tagOrBlockNumber).toBuffer()); + } + + async get(tagOrBlockNumber: string | Buffer | Tag) { + if (typeof tagOrBlockNumber === "string") { + const block = this.getBlockByTag(tagOrBlockNumber as Tag); + if (block) return block; + } + + const block = await super.get(tagOrBlockNumber); + if (block) return block; + + throw new Error("header not found"); + } + + /** + * Writes the block object to the underlying database. + * @param block + */ + async putBlock(number: Buffer, hash: Buffer, serialized: Buffer) { + let key = number; + // ensure we can store Block #0 as key "00", not "" + if (EMPTY_BUFFER.equals(key)) { + key = Buffer.from([0]); + } + const secondaryKey = hash; + await Promise.all([ + this.#blockIndexes.put(secondaryKey, key), + super.set(key, serialized) + ]); + } + + updateTaggedBlocks() { + return new Promise((resolve, reject) => { + this.base + .createValueStream({ limit: 1 }) + .on("data", (data: Buffer) => { + this.earliest = new Block(data, this.#common); + }) + .on("error", (err: Error) => { + reject(err); + }) + .on("end", () => { + resolve(void 0); + }); + + this.base + .createValueStream({ reverse: true, limit: 1 }) + .on("data", (data: Buffer) => { + this.latest = new Block(data, this.#common); + }) + .on("error", (err: Error) => { + reject(err); + }) + .on("end", () => { + resolve(void 0); + }); + }); + } +} diff --git a/src/chains/ethereum/src/data-managers/blocklog-manager.ts b/src/chains/ethereum/src/data-managers/blocklog-manager.ts new file mode 100644 index 0000000000..069151ba03 --- /dev/null +++ b/src/chains/ethereum/src/data-managers/blocklog-manager.ts @@ -0,0 +1,18 @@ +import BlockLog from "../things/blocklogs"; +import { LevelUp } from "levelup"; +import Manager from "./manager"; +import { Quantity } from "@ganache/utils"; + +export default class BlockLogManager extends Manager { + constructor(base: LevelUp) { + super(base, BlockLog); + } + + async get(key: string | Buffer) { + const log = await super.get(key); + if (log) { + log.blockNumber = key instanceof Quantity ? key : Quantity.from(key); + } + return log; + } +} diff --git a/src/chains/ethereum/src/data-managers/manager.ts b/src/chains/ethereum/src/data-managers/manager.ts new file mode 100644 index 0000000000..49c5930334 --- /dev/null +++ b/src/chains/ethereum/src/data-managers/manager.ts @@ -0,0 +1,46 @@ +import { LevelUp } from "levelup"; +import { Data } from "@ganache/utils"; +import Tag from "../things/tags"; +const NOTFOUND = 404; + +export type Instantiable = { new (...args: any[]): T }; + +export default class Manager { + #Type: Instantiable; + #options: {}; + protected base: LevelUp; + constructor( + base: LevelUp, + type: Instantiable, + options?: ConstructorParameters>[1] + ) { + this.#Type = type; + this.#options = options; + this.base = base; + } + getRaw(key: string | Buffer | Tag): Promise { + if (typeof key === "string") { + key = Data.from(key).toBuffer(); + } + + if (key.length === 0) { + return null; + } + + return this.base.get(key).catch(e => { + if (e.status === NOTFOUND) return null; + throw e; + }) as Promise; + } + async get(key: string | Buffer) { + const raw = await this.getRaw(key); + if (!raw) return null; + return new this.#Type(raw, this.#options); + } + set(key: Buffer, value: Buffer): Promise { + return this.base.put(key, value); + } + del(key: Buffer) { + return this.base.del(key); + } +} diff --git a/src/chains/ethereum/src/data-managers/transaction-manager.ts b/src/chains/ethereum/src/data-managers/transaction-manager.ts new file mode 100644 index 0000000000..8cd74d109d --- /dev/null +++ b/src/chains/ethereum/src/data-managers/transaction-manager.ts @@ -0,0 +1,104 @@ +import Transaction from "../things/transaction"; +import Manager from "./manager"; +import TransactionPool from "../transaction-pool"; +import { EthereumInternalOptions } from "../options"; +import { LevelUp } from "levelup"; +import Blockchain from "../blockchain"; +import PromiseQueue from "@ganache/promise-queue"; +import Common from "ethereumjs-common"; +import { Data } from "@ganache/utils"; + +export default class TransactionManager extends Manager { + public readonly transactionPool: TransactionPool; + + readonly #queue = new PromiseQueue(); + #paused = false; + #resumer: Promise; + #resolver: (value: void) => void; + + constructor( + options: EthereumInternalOptions["miner"], + common: Common, + blockchain: Blockchain, + base: LevelUp + ) { + super(base, Transaction, common); + + this.transactionPool = new TransactionPool(options, blockchain); + } + + /** + * Adds the transaction to the transaction pool. + * + * Returns a promise that is only resolved in the order it was added. + * + * @param transaction + * @param secretKey + * @returns `true` if the `transaction` is immediately executable, `false` if + * it may be valid in the future. Throws if the transaction is invalid. + */ + public async add(transaction: Transaction, secretKey?: Data) { + if (this.#paused) { + await this.#resumer; + } + // Because ganache requires determinism, we can't allow varying IO times to + // potentially affect the order in which transactions are inserted into the + // pool, so we use a FIFO queue to _return_ transaction insertions in the + // order the were received. + const insertion = this.transactionPool.prepareTransaction( + transaction, + secretKey + ); + const result = await this.#queue.add(insertion); + + if (result) { + this.transactionPool.drain(); + } + return result; + } + + /** + * Immediately ignores all transactions that were in the process of being + * added to the pool. These transactions' `push` promises will be resolved + * immediately with the value `false` and will _not_ be added to the pool. + * + * Also clears all transactions that were already added to the pool. + * + * Transactions that are currently in the process of being mined may still be + * mined. + */ + public clear() { + this.#queue.clear(false); + this.transactionPool.clear(); + } + + /** + * Stop processing _new_ transactions; puts new requests in a queue. Has no + * affect if already paused. + */ + public async pause() { + if (!this.#paused) { + // stop processing new transactions immediately + this.#paused = true; + this.#resumer = new Promise(resolve => { + this.#resolver = resolve; + }); + } + + // then wait until all async things we were already processing are done + // before returning + if (this.#queue.isBusy()) { + await this.#queue.emit("idle"); + } + } + + /** + * Resume processing transactions. Has no effect if not paused. + */ + public resume = () => { + if (!this.#paused) return; + + this.#paused = false; + this.#resolver(); + }; +} diff --git a/src/chains/ethereum/src/database.ts b/src/chains/ethereum/src/database.ts new file mode 100644 index 0000000000..b20b39026b --- /dev/null +++ b/src/chains/ethereum/src/database.ts @@ -0,0 +1,171 @@ +import { AbstractLevelDOWN } from "abstract-leveldown"; +import Emittery from "emittery"; +import { dir, setGracefulCleanup } from "tmp-promise"; +import levelup, { LevelUp } from "levelup"; +import Blockchain from "./blockchain"; +import { EthereumInternalOptions } from "./options"; +const leveldown = require("leveldown"); +const sub = require("subleveldown"); +const encode = require("encoding-down"); + +setGracefulCleanup(); +const tmpOptions = { prefix: "ganache-core_", unsafeCleanup: true }; +const noop = () => Promise.resolve(); + +export default class Database extends Emittery { + public readonly blockchain: Blockchain; + readonly #options: EthereumInternalOptions["database"]; + #cleanupDirectory = noop; + #closed = false; + public directory: string = null; + public db: LevelUp = null; + public blocks: LevelUp; + public blockIndexes: LevelUp; + public blockLogs: LevelUp; + public transactions: LevelUp; + public transactionReceipts: LevelUp; + public trie: LevelUp; + public readonly initialized: boolean; + #rootStore: AbstractLevelDOWN; + + /** + * The Database handles the creation of the database, and all access to it. + * Once the database has been fully initialized it will emit a `ready` + * event. + * @param options Supports one of two options: `db` (a leveldown compliant + * store instance) or `dbPath` (the path to store/read the db instance) + * @param blockchain + */ + constructor( + options: EthereumInternalOptions["database"], + blockchain: Blockchain + ) { + super(); + + this.#options = options; + this.blockchain = blockchain; + this.#initialize(); + } + + #initialize = async () => { + const levelupOptions: any = { valueEncoding: "binary" }; + const store = this.#options.db; + let db: levelup.LevelUp; + if (store) { + this.#rootStore = encode(store, levelupOptions); + db = levelup(this.#rootStore, {}); + } else { + let directory = this.#options.dbPath; + if (!directory) { + const dirInfo = await dir(tmpOptions); + directory = dirInfo.path; + this.#cleanupDirectory = dirInfo.cleanup; + + // don't continue if we closed while we were waiting for the dir + if (this.#closed) return this.#cleanup(); + } + this.directory = directory; + + // specify an empty `prefix` for browser-based leveldown (level-js) + const leveldownOpts = { prefix: "" }; + const store = encode(leveldown(directory, leveldownOpts), levelupOptions); + this.#rootStore = store; + db = levelup(store, {}); + } + + // don't continue if we closed while we were waiting for the db + if (this.#closed) return this.#cleanup(); + + const open = db.open(); + this.trie = sub(db, "T", levelupOptions); + + this.db = db; + await open; + + // don't continue if we closed while we were waiting for it to open + if (this.#closed) return this.#cleanup(); + + this.blocks = sub(db, "b", levelupOptions); + this.blockIndexes = sub(db, "i", levelupOptions); + this.blockLogs = sub(db, "l", levelupOptions); + this.transactions = sub(db, "t", levelupOptions); + this.transactionReceipts = sub(db, "r", levelupOptions); + + return this.emit("ready"); + }; + + /** + * Call `batch` to batch `put` and `del` operations within the same + * event loop tick of the provided function. All db operations within the + * batch _must_ be executed synchronously. + * @param fn Within this function's event loop tick, all `put` and + * `del` database operations are applied in a single atomic operation. This + * provides a single write call and if any individual put/del's fail the + * entire operation fails and no modifications are made. + * @returns a Promise that resolves to the return value + * of the provided function. + */ + public batch(fn: () => T) { + const rootDb = this.#rootStore.db; + const batch = this.db.batch(); + + const originalPut = rootDb.put; + const originalDel = rootDb.del; + + rootDb.put = batch.put.bind(batch); + rootDb.del = batch.del.bind(batch); + let prom: Promise; + try { + const ret = fn(); + // PSA: don't let vscode (or yourself) rewrite this to `await` the + // `batch.write` call. The `finally` block needs to run _before_ the + // write promise has resolved. + prom = batch.write().then(() => ret); + } finally { + rootDb.put = originalPut; + rootDb.del = originalDel; + } + return prom; + } + + /** + * Gracefully closes the database and cleans up the file system and waits for + * it to fully shut down. Emits a `close` event once complete. + * Note: only emits `close` once. + */ + public async close() { + const wasClosed = this.#closed; + this.#closed = true; + await this.#cleanup(); + + // only emit `close` once + if (!wasClosed) { + this.emit("close"); + return; + } + } + + /** + * Cleans up the database connections and our tmp directory. + */ + #cleanup = async () => { + const db = this.db; + if (db) { + await new Promise((resolve, reject) => + db.close(err => { + if (err) return void reject(err); + resolve(void 0); + }) + ); + await Promise.all([ + this.blocks.close(), + this.blockIndexes.close(), + this.blockIndexes.close(), + this.transactionReceipts.close(), + this.transactions.close(), + this.trie.close() + ]); + } + return this.#cleanupDirectory(); + }; +} diff --git a/src/chains/ethereum/src/errors/coded-error.ts b/src/chains/ethereum/src/errors/coded-error.ts new file mode 100644 index 0000000000..569f924155 --- /dev/null +++ b/src/chains/ethereum/src/errors/coded-error.ts @@ -0,0 +1,63 @@ +export const ErrorCodes = { + /** + * Invalid JSON was received by the server. + * An error occurred on the server while parsing the JSON text. + */ + PARSE_ERROR: -32700, + + /** + * The JSON sent is not a valid Request object. + */ + INVALID_REQUEST: -32600, + + /** + * The method does not exist / is not available. + */ + METHOD_NOT_FOUND: -32601, + + /** + * Invalid method parameter(s). + */ + INVALID_PARAMS: -32602, + + /** + * Internal JSON-RPC error. + */ + INTERNAL_ERROR: -32603, + + /** + * Missing or invalid parameters + */ + INVALID_INPUT: -32000, + + /** + * Transaction creation failed + */ + TRANSACTION_REJECTED: -32003, + + /** + * Method is not implemented + */ + METHOD_NOT_SUPPORTED: -32004, + + /** + * Version of JSON-RPC protocol is not supported + */ + JSON_RPC_VERSION_NOT_SUPPORTED: -32006 +} as const; + +export default class CodedError extends Error { + code: number; + constructor(message: string, code: number) { + super(message); + Error.captureStackTrace(this, this.constructor); + + this.code = code; + } + + static from(error: Error, code: number) { + const codedError = new CodedError(error.message, code); + codedError.stack = error.stack; + return codedError; + } +} diff --git a/src/chains/ethereum/src/errors/errors.ts b/src/chains/ethereum/src/errors/errors.ts new file mode 100644 index 0000000000..8dad72db9b --- /dev/null +++ b/src/chains/ethereum/src/errors/errors.ts @@ -0,0 +1,35 @@ +/** + * Returned if the transaction contains an invalid signature. + */ +export const INVALID_SENDER = "invalid sender"; + +/** + * Returned if the nonce of a transaction is lower than the one present in the local chain. + */ +export const NONCE_TOO_LOW = "nonce too low"; + +/** + * Returned if a transaction's gas price is below the minimum configured for the transaction pool. + */ +export const UNDERPRICED = "transaction underpriced"; + +/** + * Returned if the transaction is specified to use less gas than required to start the invocation. + */ +export const INTRINSIC_GAS_TOO_LOW = "intrinsic gas too low"; + +/** + * Returned if a transaction's requested gas limit exceeds the maximum allowance of the current block. + */ +export const GAS_LIMIT = "exceeds block gas limit"; + +/** + * Prefix for a single VM Exception occuring when running a transaction or block + */ +export const VM_EXCEPTION = "VM Exception while processing transaction: "; + +/** + * Prefix for multiple VM Exceptions occuring when running transactions or a block + */ +export const VM_EXCEPTIONS = + "Multiple VM Exceptions while processing transactions: : \n\n"; diff --git a/src/chains/ethereum/src/errors/runtime-error.ts b/src/chains/ethereum/src/errors/runtime-error.ts new file mode 100644 index 0000000000..47d16569cd --- /dev/null +++ b/src/chains/ethereum/src/errors/runtime-error.ts @@ -0,0 +1,69 @@ +import { EVMResult } from "ethereumjs-vm/dist/evm/evm"; +import { VM_EXCEPTION } from "./errors"; +import { Data } from "@ganache/utils"; +import { rawDecode } from "ethereumjs-abi"; +import CodedError, { ErrorCodes } from "./coded-error"; + +const REVERT_REASON = Buffer.from("08c379a0", "hex"); // keccak("Error(string)").slice(0, 4) + +export enum RETURN_TYPES { + TRANSACTION_HASH, + RETURN_VALUE +} + +export default class RuntimeError extends CodedError { + public code: typeof ErrorCodes.INVALID_INPUT; + public data: { + hash: string; + programCounter: number; + result: string; + reason?: string; + message: string; + }; + constructor( + transactionHash: Buffer, + result: EVMResult, + returnType: RETURN_TYPES + ) { + const execResult = result.execResult; + const error = execResult.exceptionError.error; + let message = VM_EXCEPTION + error; + + super(message, ErrorCodes.INVALID_INPUT); + + Error.captureStackTrace(this, this.constructor); + this.name = this.constructor.name; + + const returnValue = execResult.returnValue; + const hash = `0x${transactionHash.toString("hex")}`; + let reason: string | null; + if ( + returnValue.length > 4 && + REVERT_REASON.compare(returnValue, 0, 4) === 0 + ) { + try { + // it is possible for the `returnValue` to be gibberish that can't be + // decoded. See: https://github.com/trufflesuite/ganache-core/pull/452 + reason = rawDecode(["bytes"], returnValue.slice(4))[0].toString(); + message += " " + reason; + } catch { + // ignore error since reason string recover is impossible + reason = null; + } + } else { + reason = null; + } + + this.message = message; + this.data = { + hash: hash, + programCounter: execResult.runState.programCounter, + result: + returnType === RETURN_TYPES.TRANSACTION_HASH + ? hash + : Data.from(returnValue || "0x").toString(), + reason: reason, + message: error + }; + } +} diff --git a/src/chains/ethereum/src/helpers/assert-arg-length.ts b/src/chains/ethereum/src/helpers/assert-arg-length.ts new file mode 100644 index 0000000000..29f00476e1 --- /dev/null +++ b/src/chains/ethereum/src/helpers/assert-arg-length.ts @@ -0,0 +1,27 @@ +type UnknownFn = (this: unknown, ...args: any[]) => unknown; +type FunctionPropertyDescriptor = TypedPropertyDescriptor< + T +>; +export function assertArgLength(min: number, max: number = min) { + return function ( + target: O, + propertyKey: keyof O, + descriptor: FunctionPropertyDescriptor + ) { + const original = descriptor.value; + descriptor.value = function (this: unknown) { + const length = arguments.length; + if (length < min || length > max) { + throw new Error( + `Incorrect number of arguments. '${propertyKey}' requires ${ + min === max + ? `exactly ${min} ${min === 1 ? "argument" : "arguments"}.` + : `between ${min} and ${max} arguments.` + }` + ); + } + return Reflect.apply(original, this, arguments); + } as T; + return descriptor as FunctionPropertyDescriptor; + }; +} diff --git a/src/chains/ethereum/src/helpers/filter-parsing.ts b/src/chains/ethereum/src/helpers/filter-parsing.ts new file mode 100644 index 0000000000..e9f2f82d15 --- /dev/null +++ b/src/chains/ethereum/src/helpers/filter-parsing.ts @@ -0,0 +1,62 @@ +import { Quantity } from "@ganache/utils"; +import Blockchain from "../blockchain"; +import Address from "../things/address"; +import { FilterArgs, RangeFilterArgs } from "../types/filters"; + +export function parseFilterDetails( + filter: Pick +) { + // `filter.address` may be a single address or an array + const addresses = filter.address + ? (Array.isArray(filter.address) + ? filter.address + : [filter.address] + ).map(a => Address.from(a.toLowerCase()).toBuffer()) + : []; + const topics = filter.topics ? filter.topics : []; + return { addresses, topics }; +} + +export function parseFilterRange( + filter: Omit, + blockchain: Blockchain +) { + const latestBlock = blockchain.blocks.latest.header.number; + const fromBlock = blockchain.blocks.getEffectiveNumber( + filter.fromBlock || "latest" + ); + const latestBlockNumber = latestBlock.toNumber(); + const toBlock = blockchain.blocks.getEffectiveNumber( + filter.toBlock || "latest" + ); + let toBlockNumber: number; + // don't search after the "latest" block, unless it's "pending", of course. + if (toBlock > latestBlock) { + toBlockNumber = latestBlockNumber; + } else { + toBlockNumber = toBlock.toNumber(); + } + return { + fromBlock, + toBlock, + toBlockNumber + }; +} +export function parseFilter( + filter: RangeFilterArgs = { address: [], topics: [] }, + blockchain: Blockchain +) { + const { addresses, topics } = parseFilterDetails(filter); + const { fromBlock, toBlock, toBlockNumber } = parseFilterRange( + filter, + blockchain + ); + + return { + addresses, + fromBlock, + toBlock, + toBlockNumber, + topics + }; +} diff --git a/src/chains/ethereum/src/helpers/gas-estimator.ts b/src/chains/ethereum/src/helpers/gas-estimator.ts new file mode 100644 index 0000000000..9372cc2bb9 --- /dev/null +++ b/src/chains/ethereum/src/helpers/gas-estimator.ts @@ -0,0 +1,273 @@ +import { Quantity } from "@ganache/utils"; +import { BN } from "ethereumjs-util"; +import RuntimeError, { RETURN_TYPES } from "../errors/runtime-error"; + +const bn = (val = 0) => new (BN as any)(val); +const STIPEND = bn(2300); +const MULTIPLE = 64 / 63; + +const check = set => opname => set.has(opname); +const isCall = check( + new Set(["CALL", "DELEGATECALL", "STATICCALL", "CALLCODE"]) +); +const isCallOrCallcode = check(new Set(["CALL", "CALLCODE"])); +const isCreate = check(new Set(["CREATE", "CREATE2"])); +const isTerminator = check( + new Set(["STOP", "RETURN", "REVERT", "INVALID", "SELFDESTRUCT"]) +); + +const stepTracker = () => { + const sysOps = []; + const allOps = []; + const preCompile = new Set(); + let preCompileCheck = false; + let precompileCallDepth = 0; + return { + collect: info => { + if (preCompileCheck) { + if (info.depth === precompileCallDepth) { + // If the current depth is unchanged. + // we record its position. + preCompile.add(allOps.length - 1); + } + // Reset the flag immediately here + preCompileCheck = false; + } + if (isCall(info.opcode.name)) { + info.stack = info.stack.map(val => val.clone()); + preCompileCheck = true; + precompileCallDepth = info.depth; + sysOps.push({ + index: allOps.length, + depth: info.depth, + name: info.opcode.name + }); + } else if (isCreate(info.opcode.name) || isTerminator(info.opcode.name)) { + sysOps.push({ + index: allOps.length, + depth: info.depth, + name: info.opcode.name + }); + } + // This goes last so we can use the length for the index ^ + allOps.push(info); + }, + isPrecompile: index => preCompile.has(index), + done: () => + !allOps.length || + sysOps.length < 2 || + !isTerminator(allOps[allOps.length - 1].opcode.name), + ops: allOps, + systemOps: sysOps + }; +}; + +const estimateGas = (generateVM, runArgs, callback) => { + exactimate(generateVM(), runArgs, (err, result) => { + if (err) return callback(err); + binSearch(generateVM, runArgs, result, (err, result) => { + if (err) return callback(err); + callback(null, result); + }); + }); +}; + +const binSearch = async (generateVM, runArgs, result, callback) => { + const MAX = Quantity.from(runArgs.block.header.gasLimit).toBigInt(); + const gasRefund = result.execResult.gasRefund; + const startingGas = gasRefund + ? result.gasEstimate.add(gasRefund) + : result.gasEstimate; + const range = { lo: startingGas, hi: startingGas }; + const isEnoughGas = async gas => { + const vm = generateVM(); // Generate fresh VM + runArgs.tx.gasLimit = gas.toBuffer(); + const result = await vm.runTx(runArgs).catch(vmerr => ({ vmerr })); + return !result.vmerr && !result.execResult.exceptionError; + }; + + if (!(await isEnoughGas(range.hi))) { + do { + range.hi = range.hi.muln(MULTIPLE); + } while (!(await isEnoughGas(range.hi))); + while (range.lo.addn(1).lt(range.hi)) { + const mid = range.lo.add(range.hi).divn(2); + if (await isEnoughGas(mid)) { + range.hi = mid; + } else { + range.lo = mid; + } + } + if (range.hi.gte(MAX)) { + if (!(await isEnoughGas(range.hi))) { + return callback( + new Error( + "gas required exceeds allowance or always failing transaction" + ) + ); + } + } + } + + result.gasEstimate = range.hi; + callback(null, result); +}; + +const exactimate = async (vm, runArgs, callback) => { + const steps = stepTracker(); + vm.on("step", steps.collect); + + const Context = (index: number, fee?: BN) => { + const base = index === 0; + let start = index; + let stop = 0; + const cost = bn(); + let sixtyFloorths = bn(); + const op = steps.ops[index]; + const next = steps.ops[index + 1]; + const intermediateCost = op.gasLeft.sub(next.gasLeft); + const callingFee = fee || bn(); + let compositeContext = false; + + function addGas(val) { + // Add to our current context, but accounted for in sixtyfloorths + if (sixtyFloorths.gtn(0)) { + if (val.gte(sixtyFloorths)) { + sixtyFloorths = bn(); + } else { + sixtyFloorths.isub(val); + } + } + cost.iadd(val); + } + + return { + start: () => start, + stop: () => stop, + setStart: val => { + start = val; + compositeContext = true; + }, + setStop: val => { + stop = val; + }, + getCost: () => ({ cost, sixtyFloorths }), + transfer: ctx => { + const values = ctx.getCost(); + addGas(values.cost); + sixtyFloorths.iadd(values.sixtyFloorths); + }, + addSixtyFloorth: sixtyFloorth => { + sixtyFloorths.iadd(sixtyFloorth); + }, + addRange: (fee = bn()) => { + // only occurs on stack increasing ops + addGas( + steps.ops[base || compositeContext ? start : start + 1].gasLeft + .sub(steps.ops[stop].gasLeft) + .add(fee) + ); + }, + finalizeRange: () => { + let range; + // if we have a composite context and we are NOT at the final terminator + if (compositeContext && stop !== steps.ops.length - 1) { + range = steps.ops[start].gasLeft.sub(steps.ops[stop - 1].gasLeft); + addGas(range); + const tail = steps.ops[stop - 1].gasLeft.sub(steps.ops[stop].gasLeft); + range = tail.add(intermediateCost); + } else { + range = steps.ops[start].gasLeft.sub(steps.ops[stop].gasLeft); + } + range.isub(callingFee); + addGas(range); + if ( + isCallOrCallcode(op.opcode.name) && + !op.stack[op.stack.length - 3].isZero() + ) { + cost.iadd(sixtyFloorths); + const innerCost = next.gasLeft.sub(steps.ops[stop - 1].gasLeft); + if (innerCost.gt(STIPEND)) { + sixtyFloorths = cost.divn(63); + } else if (innerCost.lte(STIPEND)) { + sixtyFloorths = STIPEND.sub(innerCost); + } + } else if (stop !== steps.ops.length - 1) { + cost.iadd(sixtyFloorths); + sixtyFloorths = cost.divn(63); + } + } + }; + }; + + const getTotal = () => { + const sysops = steps.systemOps; + const ops = steps.ops; + const opIndex = cursor => sysops[cursor].index; + const stack = []; + let cursor = 0; + let context = Context(0); + while (cursor < sysops.length) { + const currentIndex = opIndex(cursor); + const current = ops[currentIndex]; + const name = current.opcode.name; + if (isCall(name) || isCreate(name)) { + if (steps.isPrecompile(currentIndex)) { + context.setStop(currentIndex + 1); + context.addRange(); + context.setStart(currentIndex + 1); + context.addSixtyFloorth(STIPEND); + } else { + context.setStop(currentIndex); + context.addRange(bn(current.opcode.fee)); + stack.push(context); + context = Context(currentIndex, bn(current.opcode.fee)); // setup next context + } + } else if (isTerminator(name)) { + // only on the last operation + context.setStop( + currentIndex + 1 < steps.ops.length ? currentIndex + 1 : currentIndex + ); + context.finalizeRange(); + const ctx = stack.pop(); + if (ctx) { + ctx.transfer(context); + context = ctx; + context.setStart(currentIndex + 1); + } else { + break; + } + } else { + throw new Error("INVALID OPCODE"); + } + cursor++; + } + const gas = context.getCost(); + return gas.cost.add(gas.sixtyFloorths); + }; + + const result = await vm.runTx(runArgs).catch(vmerr => ({ vmerr })); + const vmerr = result.vmerr; + if (vmerr) { + return callback(vmerr); + } else if (result.execResult.exceptionError) { + const error = new RuntimeError( + runArgs.tx.hash(), + result, + RETURN_TYPES.RETURN_VALUE + ); + return callback(error, result); + } else if (steps.done()) { + const estimate = result.gasUsed; + result.gasEstimate = estimate; + } else { + const actualUsed = steps.ops[0].gasLeft.sub( + steps.ops[steps.ops.length - 1].gasLeft + ); + const sixtyFloorths = getTotal().sub(actualUsed); + result.gasEstimate = result.gasUsed.add(sixtyFloorths); + } + callback(vmerr, result); +}; + +export default estimateGas; diff --git a/src/chains/ethereum/src/miner/miner.ts b/src/chains/ethereum/src/miner/miner.ts new file mode 100644 index 0000000000..26f8526f70 --- /dev/null +++ b/src/chains/ethereum/src/miner/miner.ts @@ -0,0 +1,476 @@ +import params from "../things/params"; +import Transaction from "../things/transaction"; +import { utils, Quantity, Data } from "@ganache/utils"; +import { promisify } from "util"; +import Trie from "merkle-patricia-tree"; +import Emittery from "emittery"; +import VM from "ethereumjs-vm"; +import { encode as rlpEncode } from "rlp"; +import { EthereumInternalOptions } from "../options"; +import RuntimeError, { RETURN_TYPES } from "../errors/runtime-error"; +import { Executables } from "../types/executables"; +import replaceFromHeap from "./replace-from-heap"; +import { Block, RuntimeBlock } from "../things/runtime-block"; +const { BUFFER_EMPTY, BUFFER_256_ZERO } = utils; + +export type BlockData = { + blockTransactions: Transaction[]; + transactionsTrie: Trie; + receiptTrie: Trie; + gasUsed: bigint; + timestamp: Buffer; + extraData: string; +}; + +const putInTrie = (trie: Trie, key: Buffer, val: Buffer) => + promisify(trie.put.bind(trie))(key, val); + +const sortByPrice = (values: Transaction[], a: number, b: number) => + Quantity.from(values[a].gasPrice) > Quantity.from(values[b].gasPrice); + +export default class Miner extends Emittery.Typed< + { block: { block: Block; serialized: Buffer } }, + "idle" +> { + #currentlyExecutingPrice = 0n; + #origins = new Set(); + #pending: boolean; + #isBusy: boolean = false; + #paused: boolean = false; + #resumer: Promise; + #resolver: (value: void) => void; + readonly #executables: Executables; + readonly #options: EthereumInternalOptions["miner"]; + readonly #instamine: boolean; + readonly #vm: VM; + readonly #checkpoint: () => Promise; + readonly #commit: () => Promise; + readonly #revert: () => Promise; + readonly #createBlock: (previousBlock: Block) => RuntimeBlock; + + public async pause() { + if (!this.#paused) { + this.#paused = true; + this.#resumer = new Promise(resolve => { + this.#resolver = resolve; + }); + } + + if (this.#isBusy) { + await this.once("idle"); + } + } + + public resume() { + if (!this.#paused) return; + + this.#paused = false; + this.#resolver(); + } + + // create a Heap that sorts by gasPrice + readonly #priced = new utils.Heap(sortByPrice); + /* + * @param executables A live Map of pending transactions from the transaction + * pool. The miner will update this Map by removing the best transactions + * and putting them in new blocks. + */ + constructor( + options: EthereumInternalOptions["miner"], + executables: Executables, + instamine: boolean, + vm: VM, + createBlock: (previousBlock: Block) => RuntimeBlock + ) { + super(); + const stateManager = vm.stateManager; + + this.#vm = vm; + this.#options = options; + this.#executables = executables; + this.#instamine = instamine; + this.#checkpoint = promisify(stateManager.checkpoint.bind(stateManager)); + this.#commit = promisify(stateManager.commit.bind(stateManager)); + this.#revert = promisify(stateManager.revert.bind(stateManager)); + this.#createBlock = createBlock; + + // initialize the heap with an empty array + this.#priced.init([]); + } + + /** + * @param maxTransactions: maximum number of transactions per block. If `-1`, + * unlimited. + * @param onlyOneBlock: set to `true` if only 1 block should be mined. + * + * @returns the transactions mined in the _first_ block + */ + public async mine( + block: RuntimeBlock, + maxTransactions: number = -1, + onlyOneBlock = false + ) { + if (this.#paused) { + await this.#resumer; + } + + // only allow mining a single block at a time (per miner) + if (this.#isBusy) { + // if we are currently mining a block, set the `pending` property + // so the miner knows it can immediately start mining another block once + // it is done with its current work. + this.#pending = true; + this.#updatePricedHeap(); + return; + } else { + this.#setPricedHeap(); + const result = await this.#mine(block, maxTransactions, onlyOneBlock); + this.emit("idle"); + return result; + } + } + + #mine = async ( + block: RuntimeBlock, + maxTransactions: number = -1, + onlyOneBlock = false + ) => { + const { block: lastBlock, transactions } = await this.#mineTxs( + block, + maxTransactions, + onlyOneBlock + ); + + // if there are more txs to mine, start mining them without awaiting their + // result. + if (this.#pending) { + this.#setPricedHeap(); + this.#pending = false; + if (!onlyOneBlock && this.#priced.length > 0) { + const nextBlock = this.#createBlock(lastBlock); + await this.#mine(nextBlock, this.#instamine ? 1 : -1); + } + } + return transactions; + }; + + #mineTxs = async ( + runtimeBlock: RuntimeBlock, + maxTransactions: number, + onlyOneBlock: boolean + ) => { + let block: Block; + + const { pending, inProgress } = this.#executables; + const options = this.#options; + + let keepMining = true; + const priced = this.#priced; + const legacyInstamine = this.#options.legacyInstamine; + let blockTransactions: Transaction[]; + do { + keepMining = false; + this.#isBusy = true; + + blockTransactions = []; + const transactionsTrie = new Trie(null, null); + const receiptTrie = new Trie(null, null); + + // don't mine anything at all if maxTransactions is `0` + if (maxTransactions === 0) { + await this.#checkpoint(); + await this.#commit(); + const finalizedBlockData = runtimeBlock.finalize( + transactionsTrie.root, + receiptTrie.root, + BUFFER_256_ZERO, + this.#vm.stateManager._trie.root, + BUFFER_EMPTY, // gas used + options.extraData, + [] + ); + this.emit("block", finalizedBlockData); + this.#reset(); + return { block: finalizedBlockData.block, transactions: [] }; + } + + let numTransactions = 0; + let blockGasLeft = options.blockGasLimit.toBigInt(); + let blockGasUsed = 0n; + + const blockBloom = Buffer.allocUnsafe(256).fill(0); + const promises: Promise[] = []; + + // Set a block-level checkpoint so our unsaved trie doesn't update the + // vm's "live" trie. + await this.#checkpoint(); + + // Run until we run out of items, or until the inner loop stops us. + // we don't call `shift()` here because we will may need to `replace` + // this `best` transaction with the next best transaction from the same + // origin later. + let best: Transaction; + while ((best = priced.peek())) { + const origin = Data.from(best.from).toString(); + + if (best.calculateIntrinsicGas() > blockGasLeft) { + // if the current best transaction can't possibly fit in this block + // go ahead and run the next best transaction, ignoring all other + // pending transactions from this account for this block. + // * We don't replace this "best" transaction with another from the + // same account. + // * We do "unlock" this transaction in the transaction pool's `pending` + // queue so it can be replaced, if needed. + best.locked = false; + this.#removeBestAndOrigin(origin); + continue; + } + + this.#currentlyExecutingPrice = Quantity.from(best.gasPrice).toBigInt(); + + // Set a transaction-level checkpoint so we can undo state changes in + // the case where the transaction is rejected by the VM. + await this.#checkpoint(); + + const result = await this.#runTx(best, runtimeBlock, origin, pending); + if (result !== null) { + const gasUsed = Quantity.from( + result.gasUsed.toArrayLike(Buffer) + ).toBigInt(); + if (blockGasLeft >= gasUsed) { + // if the transaction will fit in the block, commit it! + await this.#commit(); + blockTransactions[numTransactions] = best; + + blockGasLeft -= gasUsed; + blockGasUsed += gasUsed; + + // calculate receipt and tx tries + const txKey = rlpEncode(numTransactions); + promises.push(putInTrie(transactionsTrie, txKey, best.serialize())); + const receipt = best.fillFromResult(result, blockGasUsed); + promises.push(putInTrie(receiptTrie, txKey, receipt)); + + // update the block's bloom + const bloom = result.bloom.bitvector; + for (let i = 0; i < 256; i++) { + blockBloom[i] |= bloom[i]; + } + + numTransactions++; + + const pendingOrigin = pending.get(origin); + // since this transaction was successful, remove it from the "pending" + // transaction pool. + keepMining = pendingOrigin.removeBest(); + inProgress.add(best); + best.once("finalized").then(() => { + // it is in the database (or thrown out) so delete it from the + // `inProgress` Set + inProgress.delete(best); + }); + + // if we: + // * don't have enough gas left for even the smallest of transactions + // * Or if we've mined enough transactions + // we're done with this block! + // notice: when `maxTransactions` is `-1` (AKA infinite), `numTransactions === maxTransactions` + // will always return false, so this comparison works out fine. + if ( + blockGasLeft <= params.TRANSACTION_GAS || + numTransactions === maxTransactions + ) { + if (keepMining) { + // remove the newest (`best`) tx from this account's pending queue + // as we know we can fit another transaction in the block. Stick + // this tx into our `priced` heap. + keepMining = replaceFromHeap(priced, pendingOrigin); + } else { + keepMining = this.#removeBestAndOrigin(origin); + } + break; + } + + if (keepMining) { + // remove the newest (`best`) tx from this account's pending queue + // as we know we can fit another transaction in the block. Stick + // this tx into our `priced` heap. + keepMining = replaceFromHeap(priced, pendingOrigin); + } else { + // since we don't have any more txs from this account, just get the + // next bext transaction sorted in our `priced` heap. + keepMining = this.#removeBestAndOrigin(origin); + } + } else { + // didn't fit in the current block + await this.#revert(); + + // unlock the transaction so the transaction pool can reconsider this + // transaction + best.locked = false; + + // didn't fit. remove it from the priced transactions without replacing + // it with another from the account. This transaction will have to be + // run again in another block. + keepMining = priced.removeBest(); + } + } else { + // no result means the transaction is an "always failing tx", so we + // revert its changes here. + // Note: we don't clean up (`removeBest`, etc) because `runTx`'s + // error handler does the clean up itself. + await this.#revert(); + } + } + + await Promise.all(promises); + await this.#commit(); + + const finalizedBlockData = runtimeBlock.finalize( + transactionsTrie.root, + receiptTrie.root, + blockBloom, + this.#vm.stateManager._trie.root, + blockGasUsed === 0n + ? BUFFER_EMPTY + : Quantity.from(blockGasUsed).toBuffer(), + options.extraData, + blockTransactions + ); + block = finalizedBlockData.block; + const emitBlockProm = this.emit("block", finalizedBlockData); + if (legacyInstamine === true) { + // we need to wait for each block to be done mining when in legacy + // mode because things like `mine` and `miner_start` must wait for the + // first mine operation to be fully complete. + await emitBlockProm; + } + + if (onlyOneBlock) { + this.#currentlyExecutingPrice = 0n; + this.#reset(); + break; + } else { + this.#currentlyExecutingPrice = 0n; + this.#updatePricedHeap(); + + if (priced.length !== 0) { + maxTransactions = this.#instamine ? 1 : -1; + runtimeBlock = this.#createBlock(block); + } else { + // reset the miner + this.#reset(); + } + } + } while (keepMining); + + return { block, transactions: blockTransactions }; + }; + + #runTx = async ( + tx: Transaction, + block: RuntimeBlock, + origin: string, + pending: Map> + ) => { + try { + return await this.#vm.runTx({ tx, block } as any); + } catch (err) { + const errorMessage = err.message; + // We do NOT want to re-run this transaction. + // Update the `priced` heap with the next best transaction from this + // account + const pendingOrigin = pending.get(origin); + if (pendingOrigin.removeBest()) { + replaceFromHeap(this.#priced, pendingOrigin); + } else { + // if there are no more transactions from this origin remove this tx + // from the priced heap and clear out it's origin so it can accept new + // transactions from this origin. + this.#removeBestAndOrigin(origin); + } + + const e = { + execResult: { + runState: { programCounter: 0 }, + exceptionError: { error: errorMessage }, + returnValue: BUFFER_EMPTY + } + }; + tx.finalize( + "rejected", + new RuntimeError(tx.hash(), e as any, RETURN_TYPES.TRANSACTION_HASH) + ); + return null; + } + }; + + #removeBestAndOrigin = (origin: string) => { + this.#origins.delete(origin); + return this.#priced.removeBest(); + }; + + #reset = () => { + this.#origins.clear(); + this.#priced.clear(); + this.#isBusy = false; + }; + + /** + * Adds one transaction from each origin into the "priced" heap, which + * sorts each tx by gasPrice (high to low) + */ + #setPricedHeap = () => { + const { pending } = this.#executables; + const origins = this.#origins; + const priced = this.#priced; + + for (let mapping of pending) { + const heap = mapping[1]; + const next = heap.peek(); + if (next && !next.locked) { + const origin = Data.from(next.from).toString(); + origins.add(origin); + priced.push(next); + next.locked = true; + } + } + }; + + /** + * Updates the "priced" heap with transactions from origins it doesn't yet + * contain. + */ + #updatePricedHeap = () => { + const { pending } = this.#executables; + const origins = this.#origins; + const priced = this.#priced; + // Note: the `pending` Map passed here is "live", meaning it is constantly + // being updated by the `transactionPool`. This allows us to begin + // processing a block with the _current_ pending transactions, and while + // that is processing, to receive new transactions, updating our `priced` + // heap with these new pending transactions. + for (let mapping of pending) { + const heap = mapping[1]; + const next = heap.peek(); + if (next && !next.locked) { + const price = Quantity.from(next.gasPrice).toBigInt(); + + if (this.#currentlyExecutingPrice > price) { + // don't insert a transaction into the miner's `priced` heap + // if it will be better than its last + continue; + } + const origin = Data.from(next.from).toString(); + if (origins.has(origin)) { + // don't insert a transaction into the miner's `priced` heap if it + // has already queued up transactions for that origin + continue; + } + origins.add(origin); + priced.push(next); + next.locked = true; + } + } + }; +} diff --git a/src/chains/ethereum/src/miner/replace-from-heap.ts b/src/chains/ethereum/src/miner/replace-from-heap.ts new file mode 100644 index 0000000000..fe93e2f0c5 --- /dev/null +++ b/src/chains/ethereum/src/miner/replace-from-heap.ts @@ -0,0 +1,20 @@ +import { utils } from "@ganache/utils"; +import Transaction from "../things/transaction"; + +export default function replaceFromHeap( + priced: utils.Heap, + source: utils.Heap +) { + // get the next best for this account, removing from the source Heap: + const next = source.peek(); + if (next) { + // remove the current best priced transaction from this account and replace + // it with the account's next lowest nonce transaction: + priced.replaceBest(next); + next.locked = true; + return true; + } else { + // since we don't have a next, just remove this item from priced + return priced.removeBest(); + } +} diff --git a/src/chains/ethereum/src/options/chain-options.ts b/src/chains/ethereum/src/options/chain-options.ts new file mode 100644 index 0000000000..3fa46bde30 --- /dev/null +++ b/src/chains/ethereum/src/options/chain-options.ts @@ -0,0 +1,169 @@ +import { normalize } from "./helpers"; +import { Definitions } from "@ganache/options"; + +export type Hardfork = + | "constantinople" + | "byzantium" + | "petersburg" + | "istanbul" + | "muirGlacier"; + +export type ChainConfig = { + options: { + /** + * Allows unlimited contract sizes while debugging. By setting this to + * `true`, the check within the EVM for a contract size limit of 24KB (see + * [EIP-170](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md)) + * is bypassed. Setting this to `true` will cause ganache to behave + * differently than production environments. You should only set this to + * `true` during local debugging. + * + * @default false + */ + readonly allowUnlimitedContractSize: { + type: boolean; + hasDefault: true; + legacy: { + /** + * @deprecated Use chain.allowUnlimitedContractSize instead + */ + allowUnlimitedContractSize: boolean; + }; + }; + + /** + * When set to `false` only one request will be processed at a time. + * + * @default true + */ + readonly asyncRequestProcessing: { + type: boolean; + hasDefault: true; + legacy: { + /** + * @deprecated Use chain.asyncRequestProcessing instead + */ + asyncRequestProcessing: boolean; + }; + }; + + /** + * The currently configured chain id, a value used in replay-protected + * transaction signing as introduced by + * [EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md). + * + * @default 1337 + */ + readonly chainId: { + type: number; + hasDefault: true; + legacy: { + /** + * @deprecated Use chain.chainId instead + */ + chainId: number; + }; + }; + + /** + * The id of the network returned by the RPC method `net_version`. + * + * Defaults to the current timestamp, via JavaScript's `Date.now()` (the + * number of millisconds since the UNIX epoch). + * + * @default Date.now() + */ + readonly networkId: { + type: number; + hasDefault: true; + legacy: { + /** + * @deprecated Use chain.networkId instead + */ + networkId: number; + }; + }; + + /** + * Date that the first block should start. Use this feature, along with the + * `evm_increaseTime` RPC, to test time-dependent code. + */ + readonly time: { + type: number | Date; + legacy: { + /** + * @deprecated Use chain.time instead + */ + time: number | Date; + }; + }; + + /** + * Set the hardfork rules for the EVM. + * @default "muirGlacier" + */ + readonly hardfork: { + type: Hardfork; + hasDefault: true; + legacy: { + /** + * @deprecated Use chain.hardfork instead + */ + hardfork: Hardfork; + }; + }; + + /** + * Whether to report runtime errors from EVM code as RPC errors. + * + * @default false + */ + readonly vmErrorsOnRPCResponse: { + type: boolean; + hasDefault: true; + legacy: { + /** + * @deprecated Use chain.vmErrorsOnRPCResponse instead + */ + vmErrorsOnRPCResponse: boolean; + }; + }; + }; +}; + +export const ChainOptions: Definitions = { + allowUnlimitedContractSize: { + normalize, + default: () => false, + legacyName: "allowUnlimitedContractSize" + }, + asyncRequestProcessing: { + normalize, + default: () => true, + legacyName: "asyncRequestProcessing" + }, + chainId: { + normalize, + default: () => 1337, + legacyName: "chainId" + }, + networkId: { + normalize, + default: () => Date.now(), + legacyName: "networkId" + }, + time: { + normalize, + legacyName: "time" + }, + hardfork: { + normalize, + default: () => "muirGlacier", + legacyName: "hardfork" + }, + vmErrorsOnRPCResponse: { + normalize, + default: () => false, + legacyName: "vmErrorsOnRPCResponse" + } +}; diff --git a/src/chains/ethereum/src/options/database-options.ts b/src/chains/ethereum/src/options/database-options.ts new file mode 100644 index 0000000000..97dc431f9b --- /dev/null +++ b/src/chains/ethereum/src/options/database-options.ts @@ -0,0 +1,45 @@ +import { normalize } from "./helpers"; +import { Definitions } from "@ganache/options"; + +export type DatabaseConfig = { + options: { + /** + * Specify an alternative database instance, like MemDOWN + */ + db: { + type: string | object; + legacy: { + /** + * @deprecated Use database.db instead + */ + db: string | object; + }; + }; + /** + * Specify a path to a directory to save the chain database. If a database + * already exists, that chain will be initialized instead of creating a new + * one. + */ + dbPath: { + type: string; + legacy: { + /** + * @deprecated Use database.dbPath instead + */ + db_path: string; + }; + }; + }; + exclusiveGroups: [["db", "dbPath"]]; +}; + +export const DatabaseOptions: Definitions = { + db: { + normalize, + legacyName: "db" + }, + dbPath: { + normalize, + legacyName: "db_path" + } +}; diff --git a/src/chains/ethereum/src/options/helpers.ts b/src/chains/ethereum/src/options/helpers.ts new file mode 100644 index 0000000000..b2961afe57 --- /dev/null +++ b/src/chains/ethereum/src/options/helpers.ts @@ -0,0 +1 @@ +export const normalize = (rawInput: T) => rawInput; diff --git a/src/chains/ethereum/src/options/index.ts b/src/chains/ethereum/src/options/index.ts new file mode 100644 index 0000000000..388aeacc15 --- /dev/null +++ b/src/chains/ethereum/src/options/index.ts @@ -0,0 +1,80 @@ +import { ChainConfig, ChainOptions } from "./chain-options"; +import { DatabaseConfig, DatabaseOptions } from "./database-options"; +import { LoggingConfig, LoggingOptions } from "./logging-options"; +import { MinerConfig, MinerOptions } from "./miner-options"; +import { WalletConfig, WalletOptions } from "./wallet-options"; +import { + Base, + Defaults, + Definitions, + ExternalConfig, + InternalConfig, + Legacy, + LegacyOptions, + OptionName, + OptionRawType, + Options, + OptionsConfig +} from "@ganache/options"; + +export type EthereumOptions = { + chain: ChainConfig; + database: DatabaseConfig; + logging: LoggingConfig; + miner: MinerConfig; + wallet: WalletConfig; +}; + +type MakeLegacyOptions = UnionToIntersection< + { + [K in OptionName]: K extends LegacyOptions + ? Legacy + : Record>; + }[keyof Options] +>; + +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( + k: infer I +) => void + ? I + : never; + +type g = Partial< + { + [K in keyof UnionToIntersection< + MakeLegacyOptions + >]: UnionToIntersection>[K]; + } +>; + +export type EthereumLegacyOptions = Partial< + MakeLegacyOptions & + MakeLegacyOptions & + MakeLegacyOptions & + MakeLegacyOptions & + MakeLegacyOptions +>; + +export type EthereumProviderOptions = Partial< + { + [K in keyof EthereumOptions]: ExternalConfig; + } +>; + +export type EthereumInternalOptions = { + [K in keyof EthereumOptions]: InternalConfig; +}; + +export type EthereumDefaults = { + [K in keyof EthereumOptions]: Definitions; +}; + +export const ethereumDefaults: Defaults = { + chain: ChainOptions, + database: DatabaseOptions, + logging: LoggingOptions, + miner: MinerOptions, + wallet: WalletOptions +}; + +export const EthereumOptionsConfig = new OptionsConfig(ethereumDefaults); diff --git a/src/chains/ethereum/src/options/legacy-options.ts b/src/chains/ethereum/src/options/legacy-options.ts new file mode 100644 index 0000000000..113a08ba51 --- /dev/null +++ b/src/chains/ethereum/src/options/legacy-options.ts @@ -0,0 +1,25 @@ +// import { Base } from "@ganache/options"; +// import { OptionRawType, OptionName } from "@ganache/options"; +// import { ChainConfig } from "./chain-options"; +// import { DatabaseConfig } from "./database-options"; +// import { LoggingConfig } from "./logging-options"; +// import { MinerConfig } from "./miner-options"; +// import { WalletConfig } from "./wallet-options"; + +// type MakeLegacyOptions = { +// [ +// K in OptionName as void extends C["options"][K]["legacyName"] ? K : C["options"][K]["legacyName"] +// ]: +// OptionRawType +// }; + +// /** +// * @deprecated +// */ +// export type LegacyOptions = Partial< +// MakeLegacyOptions & +// MakeLegacyOptions & +// MakeLegacyOptions & +// MakeLegacyOptions & +// MakeLegacyOptions +// >; diff --git a/src/chains/ethereum/src/options/logging-options.ts b/src/chains/ethereum/src/options/logging-options.ts new file mode 100644 index 0000000000..72efb4af0b --- /dev/null +++ b/src/chains/ethereum/src/options/logging-options.ts @@ -0,0 +1,87 @@ +import { normalize } from "./helpers"; +import { Definitions } from "@ganache/options"; + +export type Logger = { + log(message?: any, ...optionalParams: any[]): void; +}; + +export type LoggingConfig = { + options: { + /** + * Set to `true` to log EVM opcodes. + * + * @default false + */ + readonly debug: { + type: boolean; + hasDefault: true; + legacy: { + /** + * @deprecated Use logging.debug instead + */ + debug: boolean; + }; + }; + + /** + * An object, like `console`, that implements a `log` function. + * + * Defaults to `console` (logs to stdout). + * + * @example + * ```typescript + * { + * log: (message: any) => { + * // handle `message` + * } + * } + * ``` + */ + readonly logger: { + type: Logger; + hasDefault: true; + legacy: { + /** + * @deprecated Use logging.logger instead + */ + logger: Logger; + }; + }; + + /** + * Set to `true` to log all RPC requests and responses. + * + * @default false + */ + readonly verbose: { + type: boolean; + hasDefault: true; + legacy: { + /** + * @deprecated Use logging.verbose instead + */ + verbose: boolean; + }; + }; + }; +}; + +const logger: Logger = { log: () => {} }; + +export const LoggingOptions: Definitions = { + debug: { + normalize, + default: () => false, + legacyName: "debug" + }, + logger: { + normalize, + default: () => logger, + legacyName: "logger" + }, + verbose: { + normalize, + default: () => false, + legacyName: "verbose" + } +}; diff --git a/src/chains/ethereum/src/options/miner-options.ts b/src/chains/ethereum/src/options/miner-options.ts new file mode 100644 index 0000000000..932aadd31a --- /dev/null +++ b/src/chains/ethereum/src/options/miner-options.ts @@ -0,0 +1,183 @@ +import { normalize } from "./helpers"; +import { Data, Quantity, utils } from "@ganache/utils"; +import { Definitions } from "@ganache/options"; +import Address from "../things/address"; + +export type MinerConfig = { + options: { + /** + * Sets the `blockTime` in seconds for automatic mining. A blockTime of `0` + * (default) enables "instamine mode", where new executable transactions + * will be mined instantly. + * + * Using the `blockTime` option is discouraged unless you have tests which + * require a specific mining interval. + * + * @default 0 // "instamine mode" + */ + blockTime: { + type: number; + hasDefault: true; + legacy: { + /** + * @deprecated Use miner.blockTime instead + */ + blockTime: number; + }; + }; + + /** + * Sets the default gas price in WEI for transactions if not otherwise specified. + * + * @default 2_000_000 + */ + gasPrice: { + type: Quantity; + rawType: string | number | bigint; + hasDefault: true; + legacy: { + /** + * @deprecated Use miner.gasPrice instead + */ + gasPrice: string | number | bigint; + }; + }; + + /** + * Sets the block gas limit in WEI. + * + * @default 12_000_000 + */ + blockGasLimit: { + type: Quantity; + rawType: string | number | bigint; + hasDefault: true; + legacy: { + /** + * @deprecated Use miner.blockGasLimit instead + */ + gasLimit: string | number | bigint; + }; + }; + + /** + * Sets the _default_ transaction gas limit in WEI. + * + * @default 9_000 + */ + defaultTransactionGasLimit: { + type: Quantity; + rawType: string | number | bigint; + hasDefault: true; + }; + + /** + * Sets the transaction gas limit in WEI for `eth_call` and + * eth_estimateGas` calls. + * + * @default 9_007_199_254_740_991 // 2**53 - 1 + */ + callGasLimit: { + type: Quantity; + rawType: string | number | bigint; + hasDefault: true; + legacy: { + /** + * @deprecated Use miner.callGasLimit instead + */ + callGasLimit: string | number | bigint; + }; + }; + + /** + * Enables legacy instamine mode, where transactions are fully mined before + * the transaction's hash is returned to the caller. If `legacyInstamine` is + * `true`, `blockTime` must be `0` (default). + * + * @default false + * @deprecated Will be removed in v4 + */ + legacyInstamine: { + type: boolean; + hasDefault: true; + // legacyInstamine is _not_ a legacy option, but it is used as one so users + // can use it just as they would other legacy options (without a namespace) + legacy: { + /** + * @deprecated Use miner.legacyInstamine instead. Will be removed in v4. + */ + legacyInstamine: boolean; + }; + }; + + /** + * Sets the address where mining rewards will go. + * + * * `{string}` hex-encoded address + * * `{number}` index of the account returned by `eth_getAccounts` + * + * @default "0x0000000000000000000000000000000000000000" + */ + coinbase: { + rawType: string | number; + type: Address | number; + hasDefault: true; + }; + + extraData: { + rawType: string; + type: Data; + hasDefault: true; + }; + }; +}; + +export const MinerOptions: Definitions = { + blockTime: { + normalize, + default: () => 0, + legacyName: "blockTime" + }, + gasPrice: { + normalize: Quantity.from, + default: () => Quantity.from(2_000_000_000), + legacyName: "gasPrice" + }, + blockGasLimit: { + normalize: Quantity.from, + default: () => Quantity.from(12_000_000), + legacyName: "gasLimit" + }, + defaultTransactionGasLimit: { + normalize: Quantity.from, + default: () => Quantity.from(90_000) + }, + callGasLimit: { + normalize: Quantity.from, + default: () => Quantity.from(Number.MAX_SAFE_INTEGER), + legacyName: "callGasLimit" + }, + coinbase: { + normalize: rawType => { + return typeof rawType === "number" ? rawType : Address.from(rawType); + }, + default: () => Address.from(utils.ACCOUNT_ZERO) + }, + legacyInstamine: { + normalize, + default: () => false, + legacyName: "legacyInstamine" + }, + extraData: { + normalize: (extra: string) => { + const bytes = Data.from(extra); + if (bytes.toBuffer().length > 32) { + throw new Error( + `extra exceeds max length. ${bytes.toBuffer().length} > 32` + ); + } + return bytes; + }, + default: () => Data.from(utils.BUFFER_EMPTY) + } +}; diff --git a/src/chains/ethereum/src/options/wallet-options.ts b/src/chains/ethereum/src/options/wallet-options.ts new file mode 100644 index 0000000000..2628835403 --- /dev/null +++ b/src/chains/ethereum/src/options/wallet-options.ts @@ -0,0 +1,225 @@ +import { normalize } from "./helpers"; +import seedrandom from "seedrandom"; +import { entropyToMnemonic } from "bip39"; + +import { Definitions } from "@ganache/options"; + +const { alea } = seedrandom; + +function randomBytes(length: number, rng: () => number) { + const buf = Buffer.allocUnsafe(length); + for (let i = 0; i < length; i++) { + buf[i] = (rng() * 255) | 0; + } + return buf; +} + +const randomAlphaNumericString = (() => { + const alphabet = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + const alphabetLength = alphabet.length; + return (length: number, rng: () => number) => { + let text = ""; + for (let i = 0; i < length; i++) { + text += alphabet[(rng() * alphabetLength) | 0]; + } + return text; + }; +})(); + +export type OptionsAccount = { + balance: string | number | bigint | Buffer; + secretKey?: string; +}; + +export type WalletConfig = { + options: { + /** + * Number of accounts to generate at startup. + * + * @default 10 + */ + totalAccounts: { + type: number; + hasDefault: true; + legacy: { + /** + * @deprecated Use wallet.totalAccounts instead + */ + total_accounts: number; + }; + }; + + /** + * Array of Accounts. Each object should have a balance key with a hexadecimal + * value. The key secretKey can also be specified, which represents the + * account's private key. If no secretKey, the address is auto-generated with + * the given balance. If specified, the key is used to determine the account's + * address. + */ + accounts: { + type: OptionsAccount[]; + legacy: { + /** + * @deprecated Use wallet.accounts instead + */ + accounts: number; + }; + }; + + /** + * Seed to use to generate a mnemonic + */ + seed: { + type: string; + hasDefault: true; + legacy: { + /** + * @deprecated Use wallet.seed instead + */ + seed: number; + }; + }; + + /** + * Use a specific HD wallet mnemonic to generate initial addresses. + */ + mnemonic: { + type: string; + hasDefault: true; + legacy: { + /** + * @deprecated Use wallet.mnemonic instead + */ + mnemonic: number; + }; + }; + + /** + * Array of addresses or address indexes specifying which accounts should be unlocked. + */ + unlockedAccounts: { + type: Array; + legacy: { + /** + * @deprecated Use wallet.unlockedAccounts instead + */ + unlocked_accounts: Array; + }; + }; + + /** + * Lock available accounts by default (good for third party transaction signing). Defaults to `false`. + * + * @default false + */ + secure: { + type: boolean; + hasDefault: true; + legacy: { + /** + * @deprecated Use wallet.secure instead + */ + secure: number; + }; + }; + + /** + * Specifies a file to save accounts and private keys to, for testing. + * + * Can be a filename or file descriptor. + * + * If specifying a filename, the directory path must already exist. + * + * See: https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options + */ + accountKeysPath: { + type: string | number; + legacy: { + /** + * @deprecated Use wallet.accountKeysPath instead + */ + account_keys_path: string | number; + }; + }; + + /** + * The default account balance, specified in ether. Defaults to `100` ether + * + * @default 100 // ether + */ + defaultBalance: { + type: number; + hasDefault: true; + legacy: { + /** + * @deprecated Use wallet.defaultBalance instead + */ + default_balance_ether: number; + }; + }; + + /** + * The hierarchical deterministic path to use when generating accounts. + * + * @default "m/44'/60'/0'/0/" + */ + hdPath: { + type: string; + hasDefault: true; + legacy: { + /** + * @deprecated Use wallet.totalAcchdPathounts instead + */ + hd_path: string; + }; + }; + }; + exclusiveGroups: [["totalAccounts", "accounts"], ["mnemonic", "seed"]]; +}; + +export const WalletOptions: Definitions = { + totalAccounts: { + normalize, + default: () => 10, + legacyName: "total_accounts" + }, + accounts: { + normalize, + legacyName: "accounts" + }, + seed: { + normalize, + default: () => randomAlphaNumericString(10, alea()), + legacyName: "seed" + }, + mnemonic: { + normalize, + default: config => + entropyToMnemonic(randomBytes(16, seedrandom(config.seed))), + legacyName: "mnemonic" + }, + unlockedAccounts: { + normalize, + legacyName: "unlocked_accounts" + }, + secure: { + normalize, + default: () => false, + legacyName: "secure" + }, + accountKeysPath: { + normalize, + legacyName: "account_keys_path" + }, + defaultBalance: { + normalize, + default: () => 100, + legacyName: "default_balance_ether" + }, + hdPath: { + normalize, + default: () => "m/44'/60'/0'/0/", + legacyName: "hd_path" + } +}; diff --git a/src/chains/ethereum/src/provider.ts b/src/chains/ethereum/src/provider.ts new file mode 100644 index 0000000000..0f4dcf841e --- /dev/null +++ b/src/chains/ethereum/src/provider.ts @@ -0,0 +1,302 @@ +import Emittery from "emittery"; +import EthereumApi from "./api"; +import { JsonRpcTypes } from "@ganache/utils"; +import { + EthereumProviderOptions, + EthereumInternalOptions, + EthereumOptionsConfig, + EthereumLegacyOptions +} from "./options"; +import cloneDeep from "lodash.clonedeep"; +import { PromiEvent, types, utils } from "@ganache/utils"; +import Wallet from "./wallet"; +declare type RequestMethods = types.KnownKeys; + +type mergePromiseGenerics = Promise< + Type extends Promise ? X : never +>; + +interface Callback { + (err?: Error, response?: JsonRpcTypes.Response): void; +} + +type RequestParams = { + readonly method: Method; + readonly params: Parameters | undefined; +}; + +const hasOwn = utils.hasOwn; + +export default class EthereumProvider + extends Emittery.Typed<{ message: any }, "connect" | "disconnect"> + implements types.Provider { + #options: EthereumInternalOptions; + #api: EthereumApi; + #executor: utils.Executor; + #wallet: Wallet; + + constructor( + options: EthereumProviderOptions | EthereumLegacyOptions = {}, + executor: utils.Executor + ) { + super(); + const providerOptions = (this.#options = EthereumOptionsConfig.normalize( + options as EthereumProviderOptions + )); + + this.#executor = executor; + const wallet = (this.#wallet = new Wallet(providerOptions.wallet)); + + this.#api = new EthereumApi(providerOptions, wallet, this); + } + + /** + * Returns the options, including defaults and generated, used to start Ganache. + */ + public getOptions() { + return cloneDeep(this.#options); + } + + /** + * Returns the unlocked accounts + */ + public getInitialAccounts() { + const accounts: Record< + string, + { unlocked: boolean; secretKey: string; balance: bigint } + > = {}; + const wallet = this.#wallet; + const unlockedAccounts = this.#wallet.unlockedAccounts; + wallet.initialAccounts.forEach(account => { + const address = account.address.toString(); + accounts[address] = { + secretKey: account.privateKey.toString(), + balance: account.balance.toBigInt(), + unlocked: unlockedAccounts.has(address) + }; + }); + return accounts; + } + + /** + * Remove an event subscription + */ + public removeListener = this.off; + + /** + * @param payload + * @param callback + * @deprecated Use the `request` method + */ + public send( + payload: JsonRpcTypes.Request, + callback?: Callback + ): undefined; + /** + * Legacy callback style API + * @param payload JSON-RPC payload + * @param callback callback + * @deprecated Batch transactions have been deprecated. Send payloads + * individually via the `request` method. + */ + public send( + payloads: JsonRpcTypes.Request[], + callback?: Callback + ): undefined; + /** + * @param method + * @param params + * @ignore Non standard! Do not use. + */ + public send( + method: RequestMethods, + params?: Parameters + ): any; + public send( + arg1: + | RequestMethods + | JsonRpcTypes.Request + | JsonRpcTypes.Request[], + arg2?: Callback | any[] + ) { + let method: RequestMethods; + let params: any; + let response: Promise<{}> | undefined; + if (typeof arg1 === "string") { + // this signature is (not) non-standard and is only a ganache thing!!! + // we should probably remove it, but I really like it so I haven't yet. + method = arg1; + params = arg2 as Parameters; + response = this.request({ method, params }); + } else if (typeof arg2 === "function") { + // handle backward compatibility with callback-style ganache-core + const callback = arg2 as Callback; + if (Array.isArray(arg1)) { + this.#legacySendPayloads(arg1).then(({ error, result }) => { + process.nextTick(callback, error, result); + }); + } else { + this.#legacySendPayload(arg1).then(({ error, result }) => { + process.nextTick(callback, error, result); + }); + } + } else { + throw new Error( + "No callback provided to provider's send function. As of web3 1.0, provider.send " + + "is no longer synchronous and must be passed a callback as its final argument." + ); + } + + return response; + } + + /** + * Legacy callback style API + * @param payload JSON-RPC payload + * @param callback callback + * @deprecated Use the `request` method. + */ + public sendAsync( + payload: JsonRpcTypes.Request, + callback?: Callback + ): void { + return this.send(payload, callback); + } + + /** + * EIP-1193 style request method + * @param args + * @returns A Promise that resolves with the method's result or rejects with a CodedError + * @EIP [1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md) + */ + public async request( + args: Parameters["length"] extends 0 + ? Pick, "method"> + : never + ): mergePromiseGenerics>; + /** + * EIP-1193 style request method + * @param args + * @returns A Promise that resolves with the method's result or rejects with a CodedError + * @EIP [1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md) + */ + public async request( + args: RequestParams + ): mergePromiseGenerics>; + public async request( + args: RequestParams + ) { + const rawResult = await this._requestRaw(args); + const value = await rawResult.value; + return JSON.parse(JSON.stringify(value)); + } + + /** + * INTERNAL. Used when the caller wants to access the orignal `PromiEvent`, which would + * otherwise be flattened into a regular Promise through the Promise chain. + * @param request + */ + public async _requestRaw({ + method, + params + }: RequestParams) { + this.#logRequest(method, params); + + const result = await this.#executor.execute(this.#api, method, params); + const promise = result.value as mergePromiseGenerics; + if (promise instanceof PromiEvent) { + promise.on("message", data => { + // EIP-1193 + this.emit("message" as never, data as never); + // legacy + this.emit( + "data" as never, + { + jsonrpc: "2.0", + method: "eth_subscription", + params: (data as any).data + } as never + ); + }); + } + const value = promise.catch((error: Error) => { + if (this.#options.chain.vmErrorsOnRPCResponse) { + if (hasOwn(error, "result")) { + // stringify the result here + // TODO: not sure why the stringification is even needed. + (error as any).result = JSON.parse( + JSON.stringify((error as any).result) + ); + } + } + // then rethrow + throw error; + }); + return { value: value }; + } + + #logRequest = ( + method: string, + params: Parameters + ) => { + const options = this.#options; + if (options.logging.verbose) { + options.logging.logger.log( + ` > ${method}: ${ + params == null + ? params + : JSON.stringify(params, null, 2).split("\n").join("\n > ") + }` + ); + } + }; + + public disconnect = async () => { + await this.emit("disconnect"); + return; + }; + + //#region legacy + #legacySendPayloads = (payloads: JsonRpcTypes.Request[]) => { + return Promise.all(payloads.map(this.#legacySendPayload)).then(results => { + let mainError: Error = null; + const responses: (JsonRpcTypes.Response | JsonRpcTypes.Error)[] = []; + results.forEach(({ error, result }, i) => { + responses.push(result); + if (error) { + if (mainError == null) { + mainError = new Error("Batch error:") as Error & { errors: [] }; + } + (mainError as any).errors[i] = error; + } + }); + return { error: mainError, result: responses }; + }); + }; + + #legacySendPayload = async (payload: JsonRpcTypes.Request) => { + const method = payload.method as RequestMethods; + const params = payload.params as Parameters; + try { + const result = await this.request({ method, params }); + return { + error: null as JsonRpcTypes.Error, + result: JsonRpcTypes.Response( + payload.id, + JSON.parse(JSON.stringify(result)) + ) + }; + } catch (error) { + let result: any; + // In order to provide `vmErrorsOnRPCResponse`, the `error` might have + // a `result` property that we need to move to the result field. Yes, + // it's super weird behavior! + if (hasOwn(error, "result")) { + result = error.result; + delete error.result; + } + return { error, result: JsonRpcTypes.Error(payload.id, error, result) }; + } + }; + //#endregion +} diff --git a/src/chains/ethereum/src/things/account.ts b/src/chains/ethereum/src/things/account.ts new file mode 100644 index 0000000000..88639235c8 --- /dev/null +++ b/src/chains/ethereum/src/things/account.ts @@ -0,0 +1,42 @@ +import { Data, Quantity } from "@ganache/utils"; +import Address from "./address"; +import { rlp, KECCAK256_RLP, KECCAK256_NULL } from "ethereumjs-util"; +import { utils } from "@ganache/utils"; + +const RPCQUANTITY_ZERO = utils.RPCQUANTITY_ZERO; + +export default class Account { + public address: Address; + public balance: Quantity; + public privateKey: Data; + public nonce: Quantity; + public stateRoot: Buffer = KECCAK256_RLP; + public codeHash: Buffer = KECCAK256_NULL; + + constructor(address: Address) { + this.address = address; + this.balance = RPCQUANTITY_ZERO; + this.nonce = RPCQUANTITY_ZERO; + } + + public static fromBuffer(buffer: Buffer) { + const account = Object.create(Account); + const arr = (rlp.decode(buffer) as any) as [Buffer, Buffer, Buffer, Buffer]; + account.nonce = Quantity.from(arr[0]); + account.balance = Quantity.from(arr[1]); + account.stateRoot = arr[2]; + account.codeHash = arr[3]; + return account; + } + + public serialize() { + return rlp.encode( + Buffer.concat([ + this.nonce.toBuffer(), + this.balance.toBuffer(), + this.stateRoot, + this.codeHash + ]) + ); + } +} diff --git a/src/chains/ethereum/src/things/address.ts b/src/chains/ethereum/src/things/address.ts new file mode 100644 index 0000000000..57576409b1 --- /dev/null +++ b/src/chains/ethereum/src/things/address.ts @@ -0,0 +1,15 @@ +import { Data } from "@ganache/utils"; + +class Address extends Data { + /** + * + * @param value + * @param byteLength the exact length the value represents when encoded as + * Ethereum JSON-RPC DATA. + */ + constructor(value: string | Buffer, byteLength: number = 20) { + super(value, byteLength); + } +} + +export default Address; diff --git a/src/chains/ethereum/src/things/blocklogs.ts b/src/chains/ethereum/src/things/blocklogs.ts new file mode 100644 index 0000000000..f71b435b47 --- /dev/null +++ b/src/chains/ethereum/src/things/blocklogs.ts @@ -0,0 +1,220 @@ +import { encode as rlpEncode, decode as rlpDecode } from "rlp"; +import { Data, Quantity } from "@ganache/utils"; +import Address from "./address"; +import { utils } from "@ganache/utils"; + +export type TransactionLog = [ + address: Buffer, + topics: Buffer[], + data: Buffer | Buffer[] +]; +export type BlockLog = [ + removed: Buffer, + transactionIndex: Buffer, + transactionHash: Buffer, + address: TransactionLog[0], + topics: TransactionLog[1], + data: TransactionLog[2] +]; + +const _raw = Symbol("raw"); +const _logs = Symbol("logs"); + +const filterByTopic = ( + expectedTopics: (string | string[])[], + logTopics: Buffer[] +) => { + // Exclude log if its number of topics is less than the number expected + if (expectedTopics.length > logTopics.length) return false; + + // for every expectedTopic, we must much the log topic in the same position + return expectedTopics.every((expectedTopic, logPosition) => { + // a `null` topic means "anything" + if (expectedTopic === null) return true; + + let expectedTopicSet: string[]; + if (!Array.isArray(expectedTopic)) { + return logTopics[logPosition].equals(Data.from(expectedTopic).toBuffer()); + } + // an empty rule set means "anything" + if (expectedTopic.length === 0) return true; + expectedTopicSet = expectedTopic; + + const logTopic = logTopics[logPosition]; + // "OR" logic, e.g., [[A, B]] means log topic in the first position matching either "A" OR "B": + return expectedTopicSet.some(expectedTopic => + logTopic.equals(Data.from(expectedTopic).toBuffer()) + ); + }); +}; + +export default class BlockLogs { + [_raw]: [blockHash: Buffer, blockLog: BlockLog[]]; + + constructor(data: Buffer) { + if (data) { + const decoded = (rlpDecode(data) as unknown) as [Buffer, BlockLog[]]; + this[_raw] = decoded; + } + } + + /** + * + * @param blockHash Creates an BlogLogs entity with an empty internal logs + * array. + */ + static create(blockHash: Buffer) { + const blockLog = Object.create(BlockLogs.prototype) as BlockLogs; + blockLog[_raw] = [blockHash, []]; + return blockLog; + } + + /** + * rlpEncode's the blockHash and logs array for db storage + */ + public serialize() { + return rlpEncode(this[_raw]); + } + + /** + * Appends the data to the internal logs array + * @param transactionIndex + * @param transactionHash + * @param log + */ + public append( + /*removed: boolean, */ transactionIndex: Buffer, + transactionHash: Buffer, + log: TransactionLog + ) { + this[_raw][1].push([ + utils.BUFFER_ZERO, // `removed`, TODO: this is used for reorgs, but we don't support them yet + transactionIndex, // transactionIndex + transactionHash, // transactionHash + log[0], // `address` + log[1], // `topics` + log[2] // `data` + ]); + } + + /** + * Returns the number of logs in the internal logs array. + */ + get length() { + return this[_raw][1].length; + } + + public blockNumber: Quantity; + + toJSON() { + return this[_logs]().toJSON(); + } + + [_logs]() { + const blockNumber = this.blockNumber; + const raw = this[_raw]; + const logs = raw[1]; + const l = this.length; + const blockHash = Data.from(raw[0]); + return { + toJSON() { + return { + *[Symbol.iterator]() { + for (let i = 0; i < l; i++) { + yield BlockLogs.logToJSON( + logs[i], + Quantity.from(i), + blockHash, + blockNumber + ); + } + } + }; + }, + *[Symbol.iterator]() { + for (let i = 0; i < l; i++) { + const log = logs[i]; + const address = log[3]; + const topics = log[4]; + yield { + address, + topics, + toJSON: () => + BlockLogs.logToJSON(log, Quantity.from(i), blockHash, blockNumber) + }; + } + } + }; + } + + /** + * + * @param log + * @param logIndex The index this log appears in the block + * @param blockHash The hash of the block + * @param blockNumber The block number + */ + protected static logToJSON( + log: BlockLog, + logIndex: Quantity, + blockHash: Data, + blockNumber: Quantity + ) { + const topics = log[4]; + const data = log[5]; + + return { + address: Address.from(log[3]), + blockHash, + blockNumber, + data: Array.isArray(data) + ? data.map(d => Data.from(d, d.length)) + : Data.from(data, data.length), + logIndex, // this is the index in the *block* + removed: log[0].equals(utils.BUFFER_ZERO) ? false : true, + topics: Array.isArray(topics) + ? topics.map(t => Data.from(t, 32)) + : Data.from(topics, 32), + transactionHash: Data.from(log[2], 32), + transactionIndex: Quantity.from(log[1]) + }; + } + + /** + * Note: you must set `this.blockNumber: Quantity` first! + * + * Topics are order-dependent. A transaction with a log with topics [A, B] will be matched by the following topic + * filters: + * ▸ [] "anything" + * ▸ [A] "A in first position (and anything after)" + * ▸ [null, B] "anything in first position AND B in second position (and anything after)" + * ▸ [A, B] "A" in first position AND B in second position (and anything after)" + * ▸ [[A, B], [A, B]] "(A OR B) in first position AND (A OR B) in second position (and anything after)" + * @param expectedAddresses + * @param expectedTopics + * @returns JSON representation of the filtered logs + */ + *filter(expectedAddresses: Buffer[], expectedTopics: (string | string[])[]) { + const logs = this[_logs](); + if (expectedAddresses.length !== 0) { + if (expectedTopics.length === 0) { + for (const log of logs) { + if (expectedAddresses.some(address => address.equals(log.address))) + yield log.toJSON(); + } + } else { + for (const log of logs) { + if (!expectedAddresses.some(address => address.equals(log.address))) + continue; + if (filterByTopic(expectedTopics, log.topics)) yield log.toJSON(); + } + } + } else if (expectedTopics.length !== 0) { + for (const log of logs) { + if (filterByTopic(expectedTopics, log.topics)) yield log.toJSON(); + } + } else { + yield* logs.toJSON(); + } + } +} diff --git a/src/chains/ethereum/src/things/params.ts b/src/chains/ethereum/src/things/params.ts new file mode 100644 index 0000000000..728ba674ea --- /dev/null +++ b/src/chains/ethereum/src/things/params.ts @@ -0,0 +1,28 @@ +// NOTE these params may need to be changed at each hardfork +// they can be tracked here: https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/common/src/hardforks/ + +export default { + /** + * Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions. + */ + TRANSACTION_GAS: 21000n, + + /** + * Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. + */ + TRANSACTION_DATA_NON_ZERO_GAS: new Map< + "constantinople" | "byzantium" | "petersburg" | "istanbul" | "muirGlacier", + bigint + >([ + ["constantinople", 68n], + ["byzantium", 68n], + ["petersburg", 68n], + ["istanbul", 68n], + ["muirGlacier", 16n] + ]), + + /** + * Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions. + */ + TRANSACTION_DATA_ZERO_GAS: 4n +}; diff --git a/src/chains/ethereum/src/things/runtime-block.ts b/src/chains/ethereum/src/things/runtime-block.ts new file mode 100644 index 0000000000..95aa14a3d9 --- /dev/null +++ b/src/chains/ethereum/src/things/runtime-block.ts @@ -0,0 +1,230 @@ +import { Data, Quantity } from "@ganache/utils"; +import { utils } from "@ganache/utils"; +import Common from "ethereumjs-common"; +import keccak from "keccak"; +import { encode as rlpEncode, decode as rlpDecode } from "rlp"; +import Transaction from "../things/transaction"; +import Address from "./address"; +import { KECCAK256_RLP_ARRAY } from "ethereumjs-util"; + +const { BUFFER_EMPTY, RPCQUANTITY_ZERO } = utils; + +type BlockHeader = { + parentHash: Data; + sha3Uncles: Data; + miner: Data; + stateRoot: Data; + transactionsRoot: Data; + receiptsRoot: Data; + logsBloom: Data; + difficulty: Quantity; + number: Quantity; + gasLimit: Quantity; + gasUsed: Quantity; + timestamp: Quantity; + extraData: Data; + mixHash: Data; + nonce: Data; +}; + +function makeHeader(raw: Buffer[]) { + const number = raw[8]; + + return { + parentHash: Data.from(raw[0], 32), + sha3Uncles: Data.from(raw[1], 32), + miner: Data.from(raw[2], 20), + stateRoot: Data.from(raw[3], 32), + transactionsRoot: Data.from(raw[4], 32), + receiptsRoot: Data.from(raw[5], 32), + logsBloom: Data.from(raw[6], 256), + difficulty: Quantity.from(raw[7], false), + // HACK: because `number` here is used as a key for the db we need to ensure + // that the value here holds an actual `0` when the raw === Buffer([]) + // the other empty buffer values aren't ever used as keys, so leaving them + // empty will probably be okay. + number: Quantity.from(raw[8], false), + gasLimit: Quantity.from(raw[9], false), + gasUsed: Quantity.from(raw[10], false), + timestamp: Quantity.from(raw[11], false), + extraData: Data.from(raw[12]), + mixHash: Data.from(raw[13], 32), + nonce: Data.from(raw[14], 8) + }; +} + +export class Block { + private readonly _size: number; + private readonly _raw: Buffer[]; + private readonly _common: Common; + private _transactions: Transaction[] = null; + private readonly _rawTransactions: Buffer[][] = null; + + public readonly header: BlockHeader; + + constructor(serialized: Buffer, common: Common) { + if (serialized) { + this._common = common; + this._size = serialized.length; + const deserialized = (rlpDecode(serialized) as any) as [ + Buffer[], + Buffer[][] + ]; + const raw = (this._raw = deserialized[0]); + this._rawTransactions = deserialized[1]; + this.header = makeHeader(raw); + } + } + + private _hash: Data; + hash() { + return ( + this._hash || + (this._hash = Data.from( + keccak("keccak256").update(rlpEncode(this._raw)).digest(), + 32 + )) + ); + } + + getTransactions() { + if (this._transactions) { + return this._transactions; + } + const common = this._common; + return (this._transactions = this._rawTransactions.map( + raw => new Transaction(raw, common) + )); + } + + toJSON(includeFullTransactions = false) { + const txFn = this.getTxFn(includeFullTransactions); + let jsonTxs: Data[] | {}[]; + + let transactions = this._transactions; + if (transactions) { + jsonTxs = transactions.map(txFn); + } else { + const common = this._common; + transactions = this._transactions = []; + jsonTxs = this._rawTransactions.map(raw => { + const tx = new Transaction(raw, common); + transactions.push(tx); + return txFn(tx); + }); + } + + return { + hash: this.hash(), + ...this.header, + + // TODO(forking): since ganache's difficulty is always 0, `totalDifficulty` for new blocks + // should just be the forked block's `difficulty`. See https://ethereum.stackexchange.com/a/7102/44640 + totalDifficulty: RPCQUANTITY_ZERO, + size: Quantity.from(this._size), + transactions: jsonTxs, + uncles: [] as string[] // this.value.uncleHeaders.map(function(uncleHash) {return to.hex(uncleHash)}) + }; + } + + getTxFn( + include = false + ): (tx: Transaction) => { [key: string]: string | Data | Quantity } | Data { + if (include) { + return (tx: Transaction) => tx.toJSON(this as any); + } else { + return (tx: Transaction) => Data.from(tx.hash()); + } + } +} + +/** + * A minimal block that can be used by the EVM to run transactions. + */ +export class RuntimeBlock { + public readonly header: { + parentHash: Buffer; + coinbase: Buffer; + number: Buffer; + gasLimit: Buffer; + timestamp: Buffer; + }; + + constructor( + number: Quantity, + parentHash: Data, + coinbase: Address, + gasLimit: Buffer, + timestamp: Quantity + ) { + const ts = timestamp.toBuffer(); + this.header = { + parentHash: parentHash.toBuffer(), + coinbase: coinbase.toBuffer(), + number: number.toBuffer(), + gasLimit: gasLimit.length === 0 ? BUFFER_EMPTY : gasLimit, + timestamp: ts.length === 0 ? BUFFER_EMPTY : ts + }; + } + + /** + * Returns the serialization of all block data and returns the hash of the + * block header. + * + * @param transactionsTrie + * @param receiptTrie + * @param bloom + * @param stateRoot + * @param gasUsed + * @param extraData + * @param transactions + */ + finalize( + transactionsTrie: Buffer, + receiptTrie: Buffer, + bloom: Buffer, + stateRoot: Buffer, + gasUsed: Buffer, + extraData: Data, + transactions: Transaction[] + ) { + const { header } = this; + const rawHeader = [ + header.parentHash, + KECCAK256_RLP_ARRAY, // uncleHash + header.coinbase, + stateRoot, + transactionsTrie, + receiptTrie, + bloom, + BUFFER_EMPTY, // difficulty + header.number, + header.gasLimit, + gasUsed, + header.timestamp, + extraData.toBuffer(), + Buffer.allocUnsafe(32).fill(0), // mixHash + Buffer.allocUnsafe(8).fill(0) // nonce + ]; + const rawTransactions = transactions.map(tx => tx.raw); + const raw = [rawHeader, rawTransactions]; + + const serialized = rlpEncode(raw); + + // make a new block, but pass `null` so it doesn't do the extra + // deserialization work since we already have everything in a deserialized + // state here. We'll just set it ourselves by reaching into the "_private" + // fields. + const block = new Block(null, null); + (block as any)._size = serialized.length; + (block as any)._raw = rawHeader; + (block as any)._rawTransactions = rawTransactions; + (block as any)._transactions = transactions; + (block as any).header = makeHeader(rawHeader); + + return { + block, + serialized + }; + } +} diff --git a/src/chains/ethereum/src/things/tags.ts b/src/chains/ethereum/src/things/tags.ts new file mode 100644 index 0000000000..2a7963a2e2 --- /dev/null +++ b/src/chains/ethereum/src/things/tags.ts @@ -0,0 +1,29 @@ +enum Tag { + EARLIEST = "earliest", + LATEST = "latest", + PENDING = "pending" +} +enum _Tag { + earliest, + latest, + pending +} + +namespace Tag { + export function normalize(tag: keyof typeof _Tag | Tag): Tag { + if (typeof tag === "string") { + return (Tag)[tag.toUpperCase()]; + } else { + switch (tag) { + case _Tag.earliest: + return Tag.EARLIEST; + case _Tag.latest: + return Tag.LATEST; + case _Tag.pending: + return Tag.PENDING; + } + } + } +} + +export default Tag; diff --git a/src/chains/ethereum/src/things/transaction-receipt.ts b/src/chains/ethereum/src/things/transaction-receipt.ts new file mode 100644 index 0000000000..aa02c54b62 --- /dev/null +++ b/src/chains/ethereum/src/things/transaction-receipt.ts @@ -0,0 +1,120 @@ +import Transaction from "./transaction"; +import { encode as rlpEncode, decode as rlpDecode } from "rlp"; +import { Data, Quantity } from "@ganache/utils"; +import BlockLogs, { TransactionLog } from "./blocklogs"; +import { utils } from "@ganache/utils"; +import { Block } from "./runtime-block"; + +const STATUSES = [utils.RPCQUANTITY_ZERO, utils.RPCQUANTITY_ONE]; + +type OmitLastType]> = T extends [ + ...infer A, + infer _L +] + ? A + : never; +type FullRawReceipt = [ + status: Buffer, + cumulativeGasUsed: Buffer, + logsBloom: Buffer, + logs: Buffer[], + gasUsed: Buffer, + contractAddress: Buffer | null +]; +type RawReceipt = OmitLastType>; + +export default class TransactionReceipt { + public contractAddress: Buffer; + #gasUsed: Buffer; + raw: RawReceipt; + + constructor(data?: Buffer) { + if (data) { + const decoded = (rlpDecode(data) as unknown) as FullRawReceipt; + this.#init( + decoded[0], + decoded[1], + decoded[2], + decoded[3], + decoded[4], + decoded[5] + ); + } + } + #init = ( + status: Buffer, + cumulativeGasUsed: Buffer, + logsBloom: Buffer, + logs: Buffer[], + gasUsed: Buffer, + contractAddress: Buffer = null + ) => { + this.raw = [status, cumulativeGasUsed, logsBloom, logs]; + this.contractAddress = contractAddress; + this.#gasUsed = gasUsed; + }; + + static fromValues( + status: Buffer, + cumulativeGasUsed: Buffer, + logsBloom: Buffer, + logs: Buffer[], + gasUsed: Buffer, + contractAddress: Buffer + ) { + const receipt = new TransactionReceipt(); + receipt.#init( + status, + cumulativeGasUsed, + logsBloom, + logs, + contractAddress, + gasUsed + ); + return receipt; + } + + public serialize(all: boolean) { + if (all) { + // the database format includes the contractAddress: + return rlpEncode([ + ...this.raw, + this.#gasUsed, + this.contractAddress + ] as FullRawReceipt); + } else { + // receipt trie format: + return rlpEncode(this.raw); + } + } + + public toJSON(block: Block, transaction: Transaction) { + const raw = this.raw; + const contractAddress = + this.contractAddress.length === 0 + ? null + : Data.from(this.contractAddress); + const blockHash = block.hash(); + const blockNumber = block.header.number; + const blockLog = BlockLogs.create(blockHash.toBuffer()); + blockLog.blockNumber = blockNumber; + ((raw[3] as any) as TransactionLog[]).forEach(log => { + blockLog.append(transaction._index, transaction.hash(), log); + }); + const logs = [...blockLog.toJSON()]; + return { + transactionHash: Data.from(transaction.hash()), + transactionIndex: Quantity.from((transaction as any)._index), + blockNumber, + blockHash, + from: Data.from(transaction.from), + to: contractAddress ? null : Data.from(transaction.to), + cumulativeGasUsed: Quantity.from(raw[1]), + gasUsed: Quantity.from(this.#gasUsed), + contractAddress, + logs, + logsBloom: Data.from(raw[2], 256), + status: STATUSES[raw[0][0]] + }; + } +} diff --git a/src/chains/ethereum/src/things/transaction.ts b/src/chains/ethereum/src/things/transaction.ts new file mode 100644 index 0000000000..3d6f584a56 --- /dev/null +++ b/src/chains/ethereum/src/things/transaction.ts @@ -0,0 +1,532 @@ +import { INTRINSIC_GAS_TOO_LOW } from "../errors/errors"; +import RuntimeError, { RETURN_TYPES } from "../errors/runtime-error"; +import { utils, Data, Quantity } from "@ganache/utils"; +import params from "./params"; +import { + Transaction as EthereumJsTransaction, + FakeTransaction as EthereumJsFakeTransaction +} from "ethereumjs-tx"; +import * as ethUtil from "ethereumjs-util"; +import assert from "assert"; +import { decode as rlpDecode } from "rlp"; +import { RunTxResult } from "ethereumjs-vm/dist/runTx"; +import TransactionReceipt from "./transaction-receipt"; +import Common from "ethereumjs-common"; +import { TransactionLog } from "./blocklogs"; +import Address from "./address"; +import { ExtractValuesFromType } from "../types/extract-values-from-types"; +import { Block } from "./runtime-block"; + +const MAX_UINT64 = (1n << 64n) - 1n; +const ZERO_BUFFER = Buffer.from([0]); +const ONE_BUFFER = Buffer.from([1]); + +//#region helpers +const sign = EthereumJsTransaction.prototype.sign; +const fakeHash = function (this: Transaction) { + // this isn't memoization of the hash. previous versions of ganache-core + // created hashes in a different/incorrect way and are recorded this way + // in snapshot dbs. We are preserving the chain's immutability by using the + // stored hash instead of calculating it. + if (this._hash != null) { + return this._hash; + } + return EthereumJsFakeTransaction.prototype.hash.apply( + this, + (arguments as unknown) as [(boolean | undefined)?] + ); +}; + +function configZeroableField(tx: any, fieldName: string, fieldLength = 32) { + const index = tx._fields.indexOf(fieldName); + const descriptor = Object.getOwnPropertyDescriptor(tx, fieldName); + // eslint-disable-next-line accessor-pairs + Object.defineProperty(tx, fieldName, { + set: v => { + descriptor.set.call(tx, v); + v = ethUtil.toBuffer(v); + assert( + fieldLength >= v.length, + `The field ${fieldName} must not have more ${fieldLength} bytes` + ); + tx._originals[index] = v; + }, + get: () => { + return tx._originals[index]; + } + }); +} + +/** + * etheruemjs-tx's Transactions don't behave quite like we need them to, so + * we're monkey-patching them to do what we want here. + * @param {Transaction} tx The Transaction to fix + * @param {Object} [data] The data object + */ +function fixProps(tx: any, data: any) { + // ethereumjs-tx doesn't allow for a `0` value in fields, but we want it to + // in order to differentiate between a value that isn't set and a value + // that is set to 0 in a fake transaction. + // Once https://github.com/ethereumjs/ethereumjs-tx/issues/112 is figured + // out we can probably remove this fix/hack. + // We keep track of the original value and return that value when + // referenced by its property name. This lets us properly encode a `0` as + // an empty buffer while still being able to differentiate between a `0` + // and `null`/`undefined`. + tx._originals = []; + const fieldNames = ["nonce", "gasPrice", "gasLimit", "value"] as const; + fieldNames.forEach(fieldName => configZeroableField(tx, fieldName, 32)); + + // Ethereumjs-tx doesn't set the _chainId value whenever the v value is set, + // which causes transaction signing to fail on transactions that include a + // chain id in the v value (like ethers.js does). + // Whenever the v value changes we need to make sure the chainId is also set. + const vDescriptors = Object.getOwnPropertyDescriptor(tx, "v"); + // eslint-disable-next-line accessor-pairs + Object.defineProperty(tx, "v", { + set: v => { + vDescriptors.set.call(tx, v); + // calculate chainId from signature + const sigV = ethUtil.bufferToInt(tx.v); + let chainId = Math.floor((sigV - 35) / 2); + if (chainId < 0) { + chainId = 0; + } + tx._chainId = chainId || 0; + } + }); +} + +function makeFake(tx: any, data: any) { + if (tx.isFake()) { + /** + * @prop {Buffer} from (read/write) Set from address to bypass transaction + * signing on fake transactions. + */ + Object.defineProperty(tx, "from", { + enumerable: true, + configurable: true, + get: tx.getSenderAddress.bind(tx), + set: val => { + if (val) { + tx._from = ethUtil.toBuffer(val); + } else { + tx._from = null; + } + } + }); + + if (data && data.from) { + tx.from = data.from; + } + + tx.hash = fakeHash; + } +} + +/** + * Parses the given data object and adds its properties to the given tx. + * @param {Transaction} tx + * @param {Object} [data] + */ +function initData(tx: Transaction, data: any) { + if (data) { + let parts: Buffer[]; + if (typeof data === "string") { + //hex + parts = (rlpDecode(Data.from(data).toBuffer()) as any) as Buffer[]; + } else if (Buffer.isBuffer(data)) { + // Buffer + parts = (rlpDecode(data) as any) as Buffer[]; + } else if (data.type === "Buffer") { + // wire Buffer + // handle case where a Buffer is sent as `{data: "Buffer", data: number[]}` + // like if someone does `web3.eth.sendRawTransaction(tx.serialize())` + const obj = data.data; + const length = obj.length; + const buf = Buffer.allocUnsafe(length); + for (let i = 0; i < length; i++) { + buf[i] = obj[i]; + } + parts = (rlpDecode(buf) as any) as Buffer[]; + } else if (Array.isArray(data)) { + // rlpdecoded data + parts = data; + } else if (typeof data === "object") { + // JSON + const keys = Object.keys(data); + tx._fields.forEach((field: any) => { + if (keys.indexOf(field) !== -1) { + tx[field] = data[field]; + } + if (field === "gasLimit") { + if (keys.indexOf("gas") !== -1) { + tx["gas"] = data["gas"]; + } + } else if (field === "data") { + if (keys.indexOf("input") !== -1) { + tx["input"] = data["input"]; + } + } + }); + + // Set chainId value from the data, if it's there and the data didn't + // contain a `v` value with chainId in it already. If we do have a + // data.chainId value let's set the interval v value to it. + if (!tx._chainId && data && data.chainId != null) { + tx.raw[tx._fields.indexOf("v")] = tx._chainId = data.chainId || 0; + } + return; + } else { + throw new Error("invalid data"); + } + + // add in our hacked-in properties + // which is the index in the block the transaciton + // was mined in + if (parts.length === tx._fields.length + 5) { + tx._from = parts.pop(); + tx.type = parts.pop()[0]; + tx._index = parts.pop(); + tx._blockNum = parts.pop(); + tx._blockHash = parts.pop(); + } + if (parts.length > tx._fields.length) { + throw new Error("wrong number of fields in data"); + } + + // make sure all the items are buffers + parts.forEach((d, i) => { + tx[tx._fields[i]] = ethUtil.toBuffer(d); + }); + } +} + +//#endregion + +type TransactionFinalization = + | { status: "confirmed"; error?: Error } + | { status: "rejected"; error: Error }; + +interface Transaction extends Omit {} +// TODO fix the EthereumJsTransaction as any via some "fake" multi-inheritance: +class Transaction extends (EthereumJsTransaction as any) { + public locked: boolean = false; + type: number; + v: Buffer; + r: Buffer; + s: Buffer; + raw: any; + _chainId: any; + _hash: Buffer; + readonly from: Buffer; + #receipt: TransactionReceipt; + #logs: TransactionLog[]; + #finalizer: (eventData: TransactionFinalization) => void; + #finalized: Promise; + /** + * @param {Object} [data] The data for this Transaction. + * @param {Number} type The `Transaction.types` bit flag for this transaction + * Can be a combination of `Transaction.types.none`, `Transaction.types.signed`, and `Transaction.types.fake`. + */ + constructor( + data: any, + common: Common, + type: number = Transaction.types.none + ) { + super(void 0, { common }); + + // EthereumJS-TX Transaction overwrites our `toJSON`, so we overwrite it back here: + this.toJSON = Transaction.prototype.toJSON.bind(this); + + this.type = type; + + fixProps(this, data); + initData(this, data); + + if (this.isFake()) { + makeFake(this, data); + } + + let finalizer: (value: TransactionFinalization) => void; + this.#finalized = new Promise(resolve => { + finalizer = (...args: any[]) => process.nextTick(resolve, ...args); + }); + this.#finalizer = finalizer; + } + + static get types() { + // values must be powers of 2 + return { + none: 0 as const, + signed: 1 as const, + fake: 2 as const + }; + } + + cost(): bigint { + return ( + Quantity.from(this.gasPrice).toBigInt() * + Quantity.from(this.gasLimit).toBigInt() + + Quantity.from(this.value).toBigInt() + ); + } + + /** + * Returns a Promise that is resolve with the confirmation status and, if + * appropriate, an error property. + * + * Note: it is possible to be confirmed AND + * + * @param event "finalized" + */ + once(event: "finalized") { + return this.#finalized; + } + + /** + * Mark this transaction as finalized, notifying all past and future + * "finalized" event subscribers. + * + * Note: + * + * @param status + * @param error + */ + finalize(status: "confirmed" | "rejected", error: Error = null) { + // resolves the `#finalized` promise + this.#finalizer({ status, error }); + } + + /** + * Compute the 'intrinsic gas' for a message with the given data. + * @param data The transaction's data + * @param hardfork The hardfork use to determine gas costs + */ + public static calculateIntrinsicGas( + data: Buffer | null, + hardfork: + | "constantinople" + | "byzantium" + | "petersburg" + | "istanbul" + | "muirGlacier" + ) { + // Set the starting gas for the raw transaction + let gas = params.TRANSACTION_GAS; + if (data) { + // Bump the required gas by the amount of transactional data + const dataLength = data.byteLength; + if (dataLength > 0) { + const TRANSACTION_DATA_NON_ZERO_GAS = params.TRANSACTION_DATA_NON_ZERO_GAS.get( + hardfork + ); + const TRANSACTION_DATA_ZERO_GAS = params.TRANSACTION_DATA_ZERO_GAS; + + // Zero and non-zero bytes are priced differently + let nonZeroBytes: bigint = 0n; + for (const b of data) { + if (b !== 0) { + nonZeroBytes++; + } + } + // Make sure we don't exceed uint64 for all data combinations. + if ((MAX_UINT64 - gas) / TRANSACTION_DATA_NON_ZERO_GAS < nonZeroBytes) { + throw new Error(INTRINSIC_GAS_TOO_LOW); + } + gas += nonZeroBytes * TRANSACTION_DATA_NON_ZERO_GAS; + + const z = BigInt(dataLength) - nonZeroBytes; + if ((MAX_UINT64 - gas) / TRANSACTION_DATA_ZERO_GAS < z) { + throw new Error(INTRINSIC_GAS_TOO_LOW); + } + gas += z * TRANSACTION_DATA_ZERO_GAS; + } + } + return gas; + } + /** + * Compute the 'intrinsic gas' for a message with the given data. + */ + public calculateIntrinsicGas(): bigint { + return Transaction.calculateIntrinsicGas(this.data, this._common._hardfork); + } + + /** + * Prepares arbitrary JSON data for use in a Transaction. + * @param {Object} json JSON object representing the Transaction + * @param {Number} type The `Transaction.types` bit flag for this transaction + * Can be a combination of `Transaction.types.none`, `Transaction.types.signed`, and `Transaction.types.fake`. + */ + static fromJSON( + json: any, + common: Common, + type: ExtractValuesFromType + ) { + let toAccount: Buffer; + if (json.to) { + // Remove all padding and make it easily comparible. + const buf = Data.from(json.to).toBuffer(); + + if (buf.equals(utils.BUFFER_ZERO)) { + // if the address is 0x0 make it 0x0{20} + toAccount = utils.ACCOUNT_ZERO; + } else { + toAccount = buf; + } + } + const data = json.data || json.input; + const options = { + nonce: Data.from(json.nonce).toBuffer(), + from: Data.from(json.from).toBuffer(), + value: Quantity.from(json.value).toBuffer(), + gasLimit: Quantity.from(json.gas || json.gasLimit).toBuffer(), + gasPrice: Quantity.from(json.gasPrice).toBuffer(), + data: data ? Data.from(data).toBuffer() : null, + to: toAccount, + v: Data.from(json.v).toBuffer(), + r: Data.from(json.r).toBuffer(), + s: Data.from(json.s).toBuffer() + }; + + const tx = new Transaction(options, common, type); + tx._hash = json.hash ? Data.from(json.hash).toBuffer() : null; + tx._from = json.from ? Data.from(json.from).toBuffer() : null; + return tx; + } + + /** + * Encodes the Transaction in order to be used in a database. Can be decoded + * into an identical Transaction via `Transaction.decode(encodedTx)`. + */ + encode() { + const resultJSON = { + hash: Data.from(this.hash()).toString(), + nonce: Quantity.from(this.nonce).toString() || "0x", + from: Data.from(this.from).toString(), + to: Data.from(this.to).toString(), + value: Quantity.from(this.value).toString(), + gas: Quantity.from(this.gasLimit).toString(), + gasPrice: Quantity.from(this.gasPrice).toString(), + data: this.data ? this.data.toString("hex") : null, + v: Quantity.from(this.v).toString(), + r: Quantity.from(this.r).toString(), + s: Quantity.from(this.s).toString(), + _type: this.type + }; + return resultJSON; + } + + isFake() { + return (this.type & Transaction.types.fake) === Transaction.types.fake; + } + + isSigned() { + return (this.type & Transaction.types.signed) === Transaction.types.signed; + } + + /** + * Compares the transaction's nonce value to the given expectedNonce taking in + * to account the type of transaction and comparison rules for each type. + * + * In a signed transaction a nonce of Buffer([]) is the same as Buffer([0]), + * but in a fake transaction Buffer([]) is null and Buffer([0]) is 0. + * + * @param {Buffer} expectedNonce The value of the from account's next nonce. + */ + validateNonce(expectedNonce: any) { + let nonce; + if (this.isSigned() && this.nonce.length === 0) { + nonce = utils.BUFFER_ZERO; + } else { + nonce = this.nonce; + } + return nonce.equals(expectedNonce); + } + + /** + * Signs the transaction and sets the `type` bit for `signed` to 1, + * i.e., `isSigned() === true` + */ + sign(secretKey: Buffer) { + this.type |= Transaction.types.signed; + return sign.call(this, secretKey); + } + + /** + * Returns a JSON-RPC spec compliant representation of this Transaction. + * + * @param {Object} block The block this Transaction appears in. + */ + toJSON(block?: Block) { + let blockHash: Data; + let blockNum: Quantity; + if (block) { + blockHash = block.hash(); + blockNum = block.header.number; + } else { + blockHash = this._blockHash ? Data.from(this._blockHash, 32) : null; + blockNum = this._blockNum ? Quantity.from(this._blockNum) : null; + } + return { + hash: Data.from(this.hash(), 32), + nonce: Quantity.from(this.nonce), + blockHash: blockHash ? blockHash : null, + blockNumber: blockNum ? blockNum : null, + transactionIndex: this._index ? Quantity.from(this._index) : null, + from: Address.from(this.from), + to: this.to.length === 0 ? null : Address.from(this.to), + value: Quantity.from(this.value), + gas: Quantity.from(this.gasLimit), + gasPrice: Quantity.from(this.gasPrice), + input: Data.from(this.data), + v: Quantity.from(this.v), + r: Quantity.from(this.r), + s: Quantity.from(this.s) + }; + } + + /** + * Initializes the receipt and logs + * @param result + * @returns RLP encoded data for use in a transaction trie + */ + fillFromResult(result: RunTxResult, cumulativeGasUsed: bigint) { + const vmResult = result.execResult; + const execException = vmResult.exceptionError; + let status: Buffer; + if (execException) { + status = ZERO_BUFFER; + this.execException = new RuntimeError( + this.hash(), + result, + RETURN_TYPES.TRANSACTION_HASH + ); + } else { + status = ONE_BUFFER; + } + + const receipt = (this.#receipt = TransactionReceipt.fromValues( + status, + Quantity.from(cumulativeGasUsed).toBuffer(), + result.bloom.bitvector, + (this.#logs = vmResult.logs || ([] as TransactionLog[])), + result.createdAddress, + result.gasUsed.toArrayLike(Buffer) + )); + + return receipt.serialize(false); + } + + getReceipt() { + return this.#receipt; + } + + getLogs() { + return this.#logs; + } + + public execException: RuntimeError = null; +} + +export default Transaction; diff --git a/src/chains/ethereum/src/transaction-pool.ts b/src/chains/ethereum/src/transaction-pool.ts new file mode 100644 index 0000000000..e0ff56d6a7 --- /dev/null +++ b/src/chains/ethereum/src/transaction-pool.ts @@ -0,0 +1,319 @@ +import Emittery from "emittery"; +import Blockchain from "./blockchain"; +import { utils } from "@ganache/utils"; +import Transaction from "./things/transaction"; +import { Data, Quantity } from "@ganache/utils"; +import { GAS_LIMIT, INTRINSIC_GAS_TOO_LOW } from "./errors/errors"; +import CodedError, { ErrorCodes } from "./errors/coded-error"; +import { EthereumInternalOptions } from "./options"; +import { Executables } from "./types/executables"; + +function byNonce(values: Transaction[], a: number, b: number) { + return ( + (Quantity.from(values[b].nonce).toBigInt() || 0n) > + (Quantity.from(values[a].nonce).toBigInt() || 0n) + ); +} + +export default class TransactionPool extends Emittery.Typed<{}, "drain"> { + #options: EthereumInternalOptions["miner"]; + + /** + * Minimum price bump percentage to replace an already existing transaction (nonce) + */ + #priceBump: bigint = 10n; + + #blockchain: Blockchain; + constructor( + options: EthereumInternalOptions["miner"], + blockchain: Blockchain + ) { + super(); + this.#blockchain = blockchain; + this.#options = options; + } + public readonly executables: Executables = { + inProgress: new Set(), + pending: new Map() + }; + readonly #origins: Map> = new Map(); + readonly #accountPromises = new Map>(); + + /** + * Inserts a transaction into the pending queue, if executable, or future pool + * if not. + * + * @param transaction + * @param secretKey + * @returns data that can be used to drain the queue + */ + public async prepareTransaction(transaction: Transaction, secretKey?: Data) { + let err: Error; + + err = this.#validateTransaction(transaction); + if (err != null) { + throw err; + } + + const from = Data.from(transaction.from); + let transactionNonce: bigint; + if (secretKey == null || transaction.nonce.length !== 0) { + transactionNonce = Quantity.from(transaction.nonce).toBigInt() || 0n; + if (transactionNonce < 0n) { + throw new Error("Transaction nonce cannot be negative."); + } + } + + const origin = from.toString(); + + // We await the `transactorNoncePromise` async request to ensure we process + // transactions in FIFO order *by account*. We look up accounts because + // ganache fills in missing nonces automatically, and we need to do it in + // order. + // The trick here is that we might actually get the next nonce from the + // account's pending executable transactions, not the account... + // But another transaction might currently be getting the nonce from the + // account, if it is, we need to wait for it to be done doing that. Hence: + let transactorNoncePromise = this.#accountPromises.get(origin); + if (transactorNoncePromise) { + await transactorNoncePromise; + } + + // we should _probably_ cache `highestNonce`, but it's actually a really hard thing to cache as the current highest + // nonce might be invalidated (like if the sender doesn't have enough funds), so we'd have to go back to the previous + // highest nonce... but what if that previous highest nonce was also invalidated?! we have to go back to the... you + // get the picture. + // So... we currently do things sub-optimally: + // if we currently have txs in `executableOriginTransactions`, we iterate over them to find the highest nonce + // and use that. Otherwise, we just fetch it from the database. + // Beware! There might still be race conditions here: + // * if the highest tx executes, which causes it to be removed from the `executableOriginTransactions` heap, + // then a new tx comes in _before_ the block is persisted to the database, the nonce might be of the second + // tx would be too low. + // * rough idea for a fix: transactions have a `finalize` method that is called _after_ the tx is saved. Maybe + // when tx's are executed their nonce is moved to a `highNonceByOrigin` map? We'd check this map in addition to the + // `executableOriginTransactions` map, always taking the highest of the two. + let highestNonce = 0n; + + const origins = this.#origins; + const queuedOriginTransactions = origins.get(origin); + + let isExecutableTransaction = false; + const executables = this.executables.pending; + let executableOriginTransactions = executables.get(origin); + + let length: number; + if ( + executableOriginTransactions && + (length = executableOriginTransactions.length) + ) { + // check if a transaction with the same nonce is in the origin's + // executables queue already. Replace the matching transaction or throw this + // new transaction away as neccessary. + const pendingArray = executableOriginTransactions.array; + const priceBump = this.#priceBump; + const newGasPrice = Quantity.from(transaction.gasPrice).toBigInt(); + // Notice: we're iterating over the raw heap array, which isn't + // necessarily sorted + for (let i = 0; i < length; i++) { + const currentPendingTx = pendingArray[i]; + const thisNonce = Quantity.from(currentPendingTx.nonce).toBigInt(); + if (thisNonce === transactionNonce) { + const gasPrice = Quantity.from(currentPendingTx.gasPrice).toBigInt(); + const thisPricePremium = gasPrice + (gasPrice * priceBump) / 100n; + + // if our new price is `gasPrice * priceBumpPercent` better than our + // oldPrice, throw out the old now. + if (!currentPendingTx.locked && newGasPrice > thisPricePremium) { + isExecutableTransaction = true; + // do an in-place replace without triggering a re-sort because we + // already know where this tranasaction should go in this "byNonce" + // heap. + pendingArray[i] = transaction; + + currentPendingTx.finalize( + "rejected", + new CodedError( + "Transaction replaced by better transaction", + ErrorCodes.TRANSACTION_REJECTED + ) + ); + } else { + throw new CodedError( + "replacement transaction underpriced", + ErrorCodes.TRANSACTION_REJECTED + ); + } + } + if (thisNonce > highestNonce) { + highestNonce = thisNonce; + } + } + if (secretKey && transactionNonce === void 0) { + // if we aren't signed and don't have a transactionNonce yet set it now + transactionNonce = highestNonce + 1n; + transaction.nonce = Quantity.from(transactionNonce).toBuffer(); + isExecutableTransaction = true; + highestNonce = transactionNonce; + } else if (transactionNonce === highestNonce + 1n) { + // if our transaction's nonce is 1 higher than the last transaction in the + // origin's heap we are executable. + isExecutableTransaction = true; + highestNonce = transactionNonce; + } + } else { + // since we don't have any executable transactions at the moment, we need + // to find our nonce from the account itself... + if (!transactorNoncePromise) { + transactorNoncePromise = this.#blockchain.accounts.getNonce(from); + this.#accountPromises.set(origin, transactorNoncePromise); + transactorNoncePromise.then(() => { + this.#accountPromises.delete(origin); + }); + } + const transactor = await transactorNoncePromise; + + const transactorNonce = transactor ? transactor.toBigInt() : 0n; + if (secretKey && transactionNonce === void 0) { + // if we don't have a transactionNonce, just use the account's next + // nonce and mark as executable + transactionNonce = transactorNonce ? transactorNonce : 0n; + highestNonce = transactionNonce; + isExecutableTransaction = true; + transaction.nonce = Quantity.from(transactionNonce).toBuffer(); + } else if (transactionNonce < transactorNonce) { + // it's an error if the transaction's nonce is <= the persisted nonce + throw new Error( + `the tx doesn't have the correct nonce. account has nonce of: ${transactorNonce} tx has nonce of: ${transactionNonce}` + ); + } else if (transactionNonce === transactorNonce) { + isExecutableTransaction = true; + } + } + + // now that we know we have a transaction nonce we can sign the transaction + // (if we have the secret key) + if (secretKey) { + transaction.sign(secretKey.toBuffer()); + } + + if (isExecutableTransaction) { + // if it is executable add it to the executables queue + if (executableOriginTransactions) { + executableOriginTransactions.push(transaction); + } else { + // if we don't yet have an executables queue for this origin make one now + executableOriginTransactions = utils.Heap.from(transaction, byNonce); + executables.set(origin, executableOriginTransactions); + } + + // Now we need to drain any queued transacions that were previously + // not executable due to nonce gaps into the origin's queue... + if (queuedOriginTransactions) { + let nextExpectedNonce = transactionNonce + 1n; + while (true) { + const nextTx = queuedOriginTransactions.peek(); + const nextTxNonce = Quantity.from(nextTx.nonce).toBigInt() || 0n; + if (nextTxNonce !== nextExpectedNonce) { + break; + } + + // we've got a an executable nonce! Put it in the executables queue. + executableOriginTransactions.push(nextTx); + + // And then remove this transaction from its origin's queue + if (!queuedOriginTransactions.removeBest()) { + // removeBest() returns `false` when there are no more items after + // the removed item. Let's do some cleanup when that happens. + origins.delete(origin); + break; + } + + nextExpectedNonce += 1n; + } + } + + return true; + } else { + // otherwise, put it in the future queue + if (queuedOriginTransactions) { + queuedOriginTransactions.push(transaction); + } else { + origins.set(origin, utils.Heap.from(transaction, byNonce)); + } + + return false; + } + } + + public clear() { + this.#origins.clear(); + this.#accountPromises.clear(); + this.executables.pending.clear(); + } + + /** + * Returns the transaction matching the given hash. + * + * This isn't the fastest thing... but querying for pending transactions is + * likely rare, so leaving this slow so other code paths can be faster might + * be okay. + * + * @param transactionHash + */ + public find(transactionHash: Buffer) { + const { pending, inProgress } = this.executables; + + // first search pending transactions + for (let [_, transactions] of this.#origins) { + if (transactions === undefined) continue; + const arr = transactions.array; + for (let i = 0; i < transactions.length; i++) { + const tx = arr[i]; + if (tx.hash().equals(transactionHash)) { + return tx; + } + } + } + + // then transactions eligible for execution + for (let [_, transactions] of pending) { + const arr = transactions.array; + for (let i = 0; i < transactions.length; i++) { + const tx = arr[i]; + if (tx.hash().equals(transactionHash)) { + return tx; + } + } + } + + // and finally transactions that have just been processed, but not yet saved + for (let tx of inProgress) { + if (tx.hash().equals(transactionHash)) { + return tx; + } + } + return null; + } + + readonly drain = () => { + // notify listeners (the blockchain, then the miner, eventually) that we + // have executable transactions ready + this.emit("drain"); + }; + + readonly #validateTransaction = (transaction: Transaction): Error => { + // Check the transaction doesn't exceed the current block limit gas. + if (Quantity.from(transaction.gasLimit) > this.#options.blockGasLimit) { + return new CodedError(GAS_LIMIT, ErrorCodes.INVALID_INPUT); + } + + // Should supply enough intrinsic gas + const gas = transaction.calculateIntrinsicGas(); + if (Quantity.from(transaction.gasLimit).toBigInt() < gas) { + return new CodedError(INTRINSIC_GAS_TOO_LOW, ErrorCodes.INVALID_INPUT); + } + + return null; + }; +} diff --git a/src/chains/ethereum/src/types/executables.ts b/src/chains/ethereum/src/types/executables.ts new file mode 100644 index 0000000000..7a9bcae406 --- /dev/null +++ b/src/chains/ethereum/src/types/executables.ts @@ -0,0 +1,7 @@ +import { utils } from "@ganache/utils"; +import Transaction from "../things/transaction"; + +export type Executables = { + inProgress: Set; + pending: Map>; +}; diff --git a/src/chains/ethereum/src/types/extract-values-from-types.ts b/src/chains/ethereum/src/types/extract-values-from-types.ts new file mode 100644 index 0000000000..e584aa2302 --- /dev/null +++ b/src/chains/ethereum/src/types/extract-values-from-types.ts @@ -0,0 +1 @@ +export type ExtractValuesFromType = { [I in keyof T]: T[I] }[keyof T]; diff --git a/src/chains/ethereum/src/types/filters.ts b/src/chains/ethereum/src/types/filters.ts new file mode 100644 index 0000000000..06dde6fd35 --- /dev/null +++ b/src/chains/ethereum/src/types/filters.ts @@ -0,0 +1,24 @@ +import { Data } from "@ganache/utils"; +import Emittery from "emittery"; +import Tag from "../things/tags"; + +export enum FilterTypes { + log, + block, + pendingTransaction +} +export type Topic = string | string[]; +export type BaseFilterArgs = { address?: string | string[]; topics?: Topic[] }; +export type BlockHashFilterArgs = BaseFilterArgs & { blockHash?: string }; +export type RangeFilterArgs = BaseFilterArgs & { + fromBlock?: string | Tag; + toBlock?: string | Tag; +}; +export type FilterArgs = BlockHashFilterArgs | RangeFilterArgs; + +export type Filter = { + type: FilterTypes; + updates: Data[]; + unsubscribe: Emittery.UnsubscribeFn; + filter: FilterArgs; +}; diff --git a/src/chains/ethereum/src/types/shh.ts b/src/chains/ethereum/src/types/shh.ts new file mode 100644 index 0000000000..7d2ffdc19b --- /dev/null +++ b/src/chains/ethereum/src/types/shh.ts @@ -0,0 +1 @@ +export type WhisperPostObject = any; diff --git a/src/chains/ethereum/src/types/snapshots.ts b/src/chains/ethereum/src/types/snapshots.ts new file mode 100644 index 0000000000..7b7f1d07cd --- /dev/null +++ b/src/chains/ethereum/src/types/snapshots.ts @@ -0,0 +1,24 @@ +import Emittery from "emittery"; +import { Block } from "../things/runtime-block"; + +type SinglyLinkedList = { current: T; next: SinglyLinkedList }; + +export type Snapshot = { + block: Block; + timeAdjustment: number; +}; + +export type Snapshots = { + readonly snaps: Snapshot[]; + + /** + * This is a rudimentary Singly Linked List Node. SLL implementation is up to + * you. + */ + blocks: SinglyLinkedList; + + /** + * Function that should be used to remove the "block" listener + */ + unsubscribeFromBlocks: Emittery.UnsubscribeFn | null; +}; diff --git a/src/chains/ethereum/src/types/subscriptions.ts b/src/chains/ethereum/src/types/subscriptions.ts new file mode 100644 index 0000000000..17adeaa0f2 --- /dev/null +++ b/src/chains/ethereum/src/types/subscriptions.ts @@ -0,0 +1,6 @@ +export type SubscriptionId = string; +export type SubscriptionName = + | "newHeads" + | "newPendingTransactions" + | "syncing" + | "logs"; diff --git a/src/chains/ethereum/src/types/tuple-from-union.ts b/src/chains/ethereum/src/types/tuple-from-union.ts new file mode 100644 index 0000000000..71aa7e40e1 --- /dev/null +++ b/src/chains/ethereum/src/types/tuple-from-union.ts @@ -0,0 +1,36 @@ +type TuplePrepend = [ + NewElement, + ...Tuple +]; + +type Consumer = (value: Value) => void; + +type IntersectionFromUnion = ( + Union extends unknown ? Consumer : never +) extends Consumer + ? ResultIntersection + : never; + +type OverloadedConsumerFromUnion = IntersectionFromUnion< + Union extends unknown ? Consumer : never +>; + +type UnionLast = OverloadedConsumerFromUnion extends ( + a: infer A +) => void + ? A + : never; + +type UnionExcludingLast = Exclude>; + +type TupleFromUnionRec< + RemainingUnion, + CurrentTuple extends readonly unknown[] +> = [RemainingUnion] extends [never] + ? CurrentTuple + : TupleFromUnionRec< + UnionExcludingLast, + TuplePrepend> + >; + +export type TupleFromUnion = TupleFromUnionRec; diff --git a/src/chains/ethereum/src/wallet.ts b/src/chains/ethereum/src/wallet.ts new file mode 100644 index 0000000000..64d5f1106d --- /dev/null +++ b/src/chains/ethereum/src/wallet.ts @@ -0,0 +1,451 @@ +import { utils } from "@ganache/utils"; +import { Data, Quantity } from "@ganache/utils"; +import Address from "./things/address"; +import { privateToAddress } from "ethereumjs-util"; +import Account from "./things/account"; +import secp256k1 from "secp256k1"; +import { mnemonicToSeedSync } from "bip39"; +import HDKey from "hdkey"; +import { alea as rng } from "seedrandom"; +import crypto from "crypto"; +import createKeccakHash from "keccak"; +import { writeFileSync } from "fs"; +import { EthereumInternalOptions } from "./options"; + +//#region Constants +const SCRYPT_PARAMS = { + dklen: 32, + n: 1024, // practically nothing + p: 8, + r: 1 +} as const; +const CIPHER = "aes-128-ctr"; +const WEI = utils.WEI; +//#endregion + +type OmitLastType]> = T extends [ + ...infer A, + infer _L +] + ? A + : never; +type LastType]> = T extends [ + ...infer _A, + infer L +] + ? L + : never; + +type Params = Parameters; +type LastParams = Parameters>; +const scrypt = (...args: OmitLastType) => { + return new Promise( + ( + resolve: (value: LastParams[1]) => void, + reject: (reason: LastParams[0]) => void + ) => { + crypto.scrypt.call( + crypto, + ...args, + (err: LastParams[0], derivedKey: LastParams[1]) => { + if (err) { + return void reject(err); + } + return resolve(derivedKey); + } + ); + } + ); +}; + +const uncompressedPublicKeyToAddress = (uncompressedPublicKey: Buffer) => { + const compresedPublicKey = secp256k1 + .publicKeyConvert(uncompressedPublicKey, false) + .slice(1); + const hasher = createKeccakHash("keccak256"); + (hasher as any)._state.absorb(compresedPublicKey); + return Address.from(hasher.digest().slice(-20)); +}; + +const asUUID = (uuid: Buffer | { length: 16 }) => { + return `${uuid.toString("hex", 0, 4)}-${uuid.toString( + "hex", + 4, + 6 + )}-${uuid.toString("hex", 6, 8)}-${uuid.toString( + "hex", + 8, + 10 + )}-${uuid.toString("hex", 10)}`; +}; + +type ThenArg = T extends PromiseLike ? U : T; +type EncryptType = ThenArg>; + +export default class Wallet { + readonly addresses: string[]; + readonly initialAccounts: Account[]; + readonly knownAccounts = new Set(); + readonly encryptedKeyFiles = new Map(); + readonly unlockedAccounts = new Map(); + readonly lockTimers = new Map(); + + #hdKey: HDKey; + + constructor(opts: EthereumInternalOptions["wallet"]) { + this.#hdKey = HDKey.fromMasterSeed(mnemonicToSeedSync(opts.mnemonic, null)); + + const initialAccounts = (this.initialAccounts = this.#initializeAccounts( + opts + )); + const l = initialAccounts.length; + + const knownAccounts = this.knownAccounts; + const unlockedAccounts = this.unlockedAccounts; + //#region Unlocked Accounts + const givenUnlockedAccounts = opts.unlockedAccounts; + if (givenUnlockedAccounts) { + const ul = givenUnlockedAccounts.length; + for (let i = 0; i < ul; i++) { + let arg = givenUnlockedAccounts[i]; + let address: string; + switch (typeof arg) { + case "string": + // `toLowerCase` so we handle uppercase `0X` formats + const addressOrIndex = arg.toLowerCase(); + if (addressOrIndex.indexOf("0x") === 0) { + address = addressOrIndex; + break; + } else { + // try to convert the arg string to a number. + // don't use parseInt because strings like `"123abc"` parse + // to `123`, and there is probably an error on the user's side we'd + // want to uncover. + const index = ((arg as any) as number) - 0; + // if we don't have a valid number, or the number isn't a valid JS + // integer (no bigints or decimals, please), throw an error. + if (!Number.isSafeInteger(index)) { + throw new Error(`Invalid value in unlocked_accounts: ${arg}`); + } + arg = index; + // not `break`ing here because I want this to fall through to the + // `"number"` case below. + // Refactor it if you want. + // break; // no break, please. + } + case "number": + const account = initialAccounts[arg]; + if (account == null) { + throw new Error( + `Account at index ${arg} not found. Max index available is ${ + l - 1 + }.` + ); + } + address = account.address.toString().toLowerCase(); + break; + default: + throw new Error(`Invalid value specified in unlocked_accounts`); + } + if (unlockedAccounts.has(address)) continue; + // if we don't have the secretKey for an account we use `null` + unlockedAccounts.set(address, null); + } + } + //#endregion + + //#region Configure Known + Unlocked Accounts + const accountsCache = (this.addresses = Array(l)); + for (let i = 0; i < l; i++) { + const account = initialAccounts[i]; + const address = account.address; + const strAddress = address.toString(); + accountsCache[i] = strAddress; + knownAccounts.add(strAddress); + + // if the `secure` option has been set do NOT add these accounts to the + // unlockedAccounts, unless the account was already added to + // unlockedAccounts, in which case we need to add the account's private + // key. + if (opts.secure && !unlockedAccounts.has(strAddress)) continue; + + unlockedAccounts.set(strAddress, account.privateKey); + } + //#endregion + + //#region save accounts to disk + if (opts.accountKeysPath != null) { + const fileData = { + addresses: {} as { [address: string]: string }, + private_keys: {} as { [address: string]: Data } + }; + unlockedAccounts.forEach((privateKey, address) => { + fileData.addresses[address] = address; + fileData.private_keys[address] = privateKey; + }); + writeFileSync(opts.accountKeysPath, JSON.stringify(fileData)); + } + //#endregion + } + + #seedCounter = 0n; + + #randomBytes = (length: number) => { + // Since this is a mock RPC library, the rng doesn't need to be + // cryptographically secure, and determinism is desired. + const buf = Buffer.allocUnsafe(length); + const seed = (this.#seedCounter += 1n); + const rand = rng(seed.toString()); + for (let i = 0; i < length; i++) { + buf[i] = (rand() * 255) | 0; + } + return buf; + }; + + #initializeAccounts = ( + options: EthereumInternalOptions["wallet"] + ): Account[] => { + // convert a potentially fractional balance of Ether to WEI + const balanceParts = options.defaultBalance.toString().split(".", 2); + const significand = BigInt(balanceParts[0]); + const fractionalStr = balanceParts[1] || "0"; + const fractional = BigInt(fractionalStr); + const magnitude = 10n ** BigInt(fractionalStr.length); + const defaultBalanceInWei = + WEI * significand + fractional * (WEI / magnitude); + const etherInWei = Quantity.from(defaultBalanceInWei); + let accounts: Account[]; + + let givenAccounts = options.accounts; + let accountsLength: number; + if (givenAccounts && (accountsLength = givenAccounts.length) !== 0) { + const hdKey = this.#hdKey; + const hdPath = options.hdPath; + accounts = Array(accountsLength); + for (let i = 0; i < accountsLength; i++) { + const account = givenAccounts[i]; + const secretKey = account.secretKey; + let privateKey: Data; + let address: Address; + if (!secretKey) { + const acct = hdKey.derive(hdPath + i); + address = uncompressedPublicKeyToAddress(acct.publicKey); + privateKey = Data.from(acct.privateKey); + accounts[i] = Wallet.createAccount( + Quantity.from(account.balance), + privateKey, + address + ); + } else { + privateKey = Data.from(secretKey); + const a = (accounts[i] = Wallet.createAccountFromPrivateKey( + privateKey + )); + a.balance = Quantity.from(account.balance); + } + } + } else { + const numerOfAccounts = options.totalAccounts; + if (numerOfAccounts) { + accounts = Array(numerOfAccounts); + const hdPath = options.hdPath; + const hdKey = this.#hdKey; + + for (let index = 0; index < numerOfAccounts; index++) { + const acct = hdKey.derive(hdPath + index); + const address = uncompressedPublicKeyToAddress(acct.publicKey); + const privateKey = Data.from(acct.privateKey); + accounts[index] = Wallet.createAccount( + etherInWei, + privateKey, + address + ); + } + } else { + throw new Error( + "Cannot initialize chain: either options.accounts or options.total_accounts must be specified" + ); + } + } + return accounts; + }; + + public async encrypt(privateKey: Data, passphrase: string) { + const random = this.#randomBytes(32 + 16 + 16); + const salt = random.slice(0, 32); // first 32 bytes + const iv = random.slice(32, 32 + 16); // next 16 bytes + const uuid = random.slice(32 + 16); // last 16 bytes + + const derivedKey = await scrypt(passphrase, salt, SCRYPT_PARAMS.dklen, { + ...SCRYPT_PARAMS, + N: SCRYPT_PARAMS.n + }); + const cipher = crypto.createCipheriv(CIPHER, derivedKey.slice(0, 16), iv); + const ciphertext = Buffer.concat([ + cipher.update(privateKey.toBuffer()), + cipher.final() + ]); + const mac = createKeccakHash("keccak256") + .update(Buffer.concat([derivedKey.slice(16, 32), ciphertext])) + .digest(); + return { + crypto: { + cipher: CIPHER, + ciphertext: Data.from(ciphertext), + cipherparams: { + iv: Data.from(iv) + }, + kdf: "scrypt", + kdfParams: { + ...SCRYPT_PARAMS, + salt: Data.from(salt) + }, + mac: Data.from(mac) + }, + id: asUUID(uuid), + version: 3 + }; + } + + public async decrypt(keyfile: EncryptType, passphrase: crypto.BinaryLike) { + const crypt = keyfile.crypto; + + if (crypt.cipher !== CIPHER) { + throw new Error(`keyfile cypher must be "${CIPHER}"`); + } + if (crypt.kdf !== "scrypt") { + throw new Error(`keyfile kdf must be "script"`); + } + + const kdfParams = crypt.kdfParams; + const salt = kdfParams.salt; + const mac = crypt.mac; + const ciphertext = crypt.ciphertext.toBuffer(); + + let derivedKey: Buffer; + let localMac: Buffer; + if (passphrase != null) { + try { + derivedKey = await scrypt( + passphrase, + salt.toBuffer(), + kdfParams.dklen, + { ...kdfParams, N: kdfParams.n } + ); + localMac = createKeccakHash("keccak256") + .update(Buffer.concat([derivedKey.slice(16, 32), ciphertext])) + .digest(); + } catch { + localMac = null; + } + } + + if (!localMac || !mac.toBuffer().equals(localMac)) { + throw new Error("could not decrypt key with given password"); + } + + const decipher = crypto.createDecipheriv( + crypt.cipher, + derivedKey.slice(0, 16), + crypt.cipherparams.iv.toBuffer() + ); + const plaintext = decipher.update(ciphertext); + return plaintext; + } + + public static createAccount( + balance: Quantity, + privateKey: Data, + address: Address + ) { + const account = new Account(address); + account.privateKey = privateKey; + account.balance = balance; + return account; + } + + public static createAccountFromPrivateKey(privateKey: Data) { + const address = Address.from(privateToAddress(privateKey.toBuffer())); + const account = new Account(address); + account.privateKey = privateKey; + return account; + } + + public createRandomAccount(startingSeed: string) { + // create some seeded deterministic psuedo-randomness based on the chain's + // initial starting conditions (`startingSeed`) + const seed = Buffer.concat([ + Buffer.from(startingSeed), + this.#randomBytes(64) + ]); + const acct = HDKey.fromMasterSeed(seed); + const address = uncompressedPublicKeyToAddress(acct.publicKey); + const privateKey = Data.from(acct.privateKey); + return Wallet.createAccount(utils.RPCQUANTITY_ZERO, privateKey, address); + } + + public async unlockAccount( + lowerAddress: string, + passphrase: string, + duration: number + ) { + const encryptedKeyFile = this.encryptedKeyFiles.get(lowerAddress); + if (encryptedKeyFile == null) { + return false; + } + const secretKey = await this.decrypt(encryptedKeyFile, passphrase); + + const existingTimer = this.lockTimers.get(lowerAddress); + if (existingTimer) { + clearTimeout(existingTimer); + } + + // a duration <= 0 will remain unlocked + const durationMs = (duration * 1000) | 0; + if (durationMs > 0) { + const timeout = setTimeout(this.#lockAccount, durationMs, lowerAddress); + utils.unref(timeout); + this.lockTimers.set(lowerAddress, timeout as any); + } + + this.unlockedAccounts.set(lowerAddress, Data.from(secretKey)); + return true; + } + + public async unlockUnknownAccount(lowerAddress: string, duration: number) { + if (this.unlockedAccounts.has(lowerAddress)) { + // already unlocked, return `false` since we didn't do anything + return false; + } + + // if we "know" about this account, it cannot be unlocked this way + if (this.knownAccounts.has(lowerAddress)) { + throw new Error("cannot unlock known/personal account"); + } + + // a duration <= 0 will remain unlocked + const durationMs = (duration * 1000) | 0; + if (durationMs > 0) { + const timeout = setTimeout(this.#lockAccount, durationMs, lowerAddress); + utils.unref(timeout); + this.lockTimers.set(lowerAddress, timeout as any); + } + + // otherwise, unlock it! + this.unlockedAccounts.set(lowerAddress, null); + return true; + } + + #lockAccount = (lowerAddress: string) => { + this.lockTimers.delete(lowerAddress); + this.unlockedAccounts.delete(lowerAddress); + return true; + }; + + public lockAccount(lowerAddress: string) { + if (!this.unlockedAccounts.has(lowerAddress)) return false; + + clearTimeout(this.lockTimers.get(lowerAddress)); + return this.#lockAccount(lowerAddress); + } +} diff --git a/src/chains/ethereum/tests/@types/solc/index.d.ts b/src/chains/ethereum/tests/@types/solc/index.d.ts new file mode 100644 index 0000000000..6b94b3df2c --- /dev/null +++ b/src/chains/ethereum/tests/@types/solc/index.d.ts @@ -0,0 +1,158 @@ +declare module "solc" { + export type Primitive = + | "bool" + | "string" + | "address" + | "uint8" + | "uint16" + | "uint32" + | "uint64" + | "uint128" + | "uint256" + | "int8" + | "int16" + | "int32" + | "int64" + | "int128" + | "int256" + | "bytes" + | "bytes20" + | "bytes32" + | "bool[]" + | "string[]" + | "address[]" + | "uint8[]" + | "uint16[]" + | "uint32[]" + | "uint64[]" + | "uint128[]" + | "uint256[]" + | "int8[]" + | "int16[]" + | "int32[]" + | "int64[]" + | "int128[]" + | "int256[]" + | "bytes[]" + | "bytes20[]" + | "bytes32[]"; + + export interface AbiParameter { + name: string; + type: Primitive; + } + + export interface AbiEventParameter extends AbiParameter { + indexed: boolean; + } + + export interface AbiFunction { + name: string; + type: "function" | "constructor" | "fallback"; + stateMutability: "pure" | "view" | "payable" | "nonpayable"; + constant: boolean; + payable: boolean; + inputs: Array; + outputs: Array; + } + + export interface AbiEvent { + name: string; + type: "event"; + inputs: Array; + anonymous: boolean; + } + + export type Abi = Array; + + interface CompilerInputSourceFile { + keccak256?: string; + urls: string[]; + } + interface CompilerInputSourceCode { + keccak256?: string; + content: string; + } + interface CompilerInput { + language: "Solidity" | "serpent" | "lll" | "assembly"; + settings?: any; + sources: { + [globalName: string]: CompilerInputSourceFile | CompilerInputSourceCode; + }; + } + interface CompilerOutputError { + sourceLocation?: { + file: string; + start: number; + end: number; + }; + type: "TypeError" | "InternalCompilerError" | "Exception"; + component: "general" | "ewasm"; + severity: "error" | "warning"; + message: string; + formattedMessage?: string; + } + interface CompilerOutputEvmBytecode { + object?: string; + opcodes?: string; + sourceMap?: string; + linkReferences?: + | {} + | { + [globalName: string]: { + [name: string]: { start: number; length: number }[]; + }; + }; + } + interface CompilerOutputSources { + [globalName: string]: { + id: number; + ast?: any; + legacyAST?: any; + }; + } + interface CompilerOutputContracts { + [globalName: string]: { + [contractName: string]: { + abi?: Abi; + metadata?: string; + userdoc?: any; + devdoc?: any; + ir?: string; + evm?: { + assembly?: string; + legacyAssembly?: any; + bytecode: CompilerOutputEvmBytecode; + deployedBytecode?: CompilerOutputEvmBytecode; + methodIdentifiers?: { + [methodName: string]: string; + }; + gasEstimates?: { + creation: { + codeDepositCost: string; + executionCost: string; + totalCost: string; + }; + external: { + [functionSignature: string]: string; + }; + internal: { + [functionSignature: string]: string; + }; + }; + }; + ewasm: { + wast?: string; + wasm?: string; + }; + }; + }; + } + interface CompilerOutput { + errors: CompilerOutputError[]; + sources: CompilerOutputSources; + contracts: CompilerOutputContracts; + } + type ReadCallback = (path: string) => { contents?: string; error?: string }; + function compile(input: string): string; +} diff --git a/src/chains/ethereum/tests/api/bzz/bzz.test.ts b/src/chains/ethereum/tests/api/bzz/bzz.test.ts new file mode 100644 index 0000000000..156264e3bc --- /dev/null +++ b/src/chains/ethereum/tests/api/bzz/bzz.test.ts @@ -0,0 +1,28 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; + +describe("api", () => { + describe("bzz", () => { + let provider: EthereumProvider; + before(async function () { + // GitHub Actions' windows-2019 Node v14 environment can sometimes take a + // VERY long time to run this `before`, as it is CURRENTLY the first + // @ganache/ethereum test that mocha runs (alphabetically)... and for some + // reason it is slow. + this.timeout(10000); + + provider = await getProvider(); + }); + + it("bzz_hive stub returns value", async () => { + const result = await provider.send("bzz_hive"); + assert.deepStrictEqual(result, []); + }); + + it("bzz_info stub returns value", async () => { + const result = await provider.send("bzz_info"); + assert.deepStrictEqual(result, []); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/db/db.test.ts b/src/chains/ethereum/tests/api/db/db.test.ts new file mode 100644 index 0000000000..26a0489706 --- /dev/null +++ b/src/chains/ethereum/tests/api/db/db.test.ts @@ -0,0 +1,32 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; + +describe("api", () => { + describe("db", () => { + let provider: EthereumProvider; + beforeEach(async () => { + provider = await getProvider(); + }); + + it("db_putString", async () => { + const result = await provider.send("db_putString", ["", "", ""]); + assert.deepStrictEqual(result, false); + }); + + it("db_getString", async () => { + const result = await provider.send("db_getString", ["", ""]); + assert.deepStrictEqual(result, ""); + }); + + it("db_putHex", async () => { + const result = await provider.send("db_putHex", ["", "", ""]); + assert.deepStrictEqual(result, false); + }); + + it("db_getHex", async () => { + const result = await provider.send("db_getHex", ["", ""]); + assert.deepStrictEqual(result, "0x00"); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/contracts/GetCode.sol b/src/chains/ethereum/tests/api/eth/contracts/GetCode.sol new file mode 100644 index 0000000000..49edc1c3cb --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/contracts/GetCode.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.4; + +contract GetCode {} diff --git a/src/chains/ethereum/tests/api/eth/contracts/GetStorageAt.sol b/src/chains/ethereum/tests/api/eth/contracts/GetStorageAt.sol new file mode 100644 index 0000000000..2d27d6a107 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/contracts/GetStorageAt.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.4; + +contract GetStorageAt { + uint256 public intValue1 = 123; + address public self = address(0x01); +} diff --git a/src/chains/ethereum/tests/api/eth/contracts/Logs.sol b/src/chains/ethereum/tests/api/eth/contracts/Logs.sol new file mode 100644 index 0000000000..b1aa9045fb --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/contracts/Logs.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.4; + +contract Logs { + event Event(uint256 indexed first, uint256 indexed second); + + constructor() { + emit Event(1, 2); + } + + function logNTimes(uint8 n) public { + for (uint8 i = 0; i < n; i++) { + emit Event(i, i); + } + } +} diff --git a/src/chains/ethereum/tests/api/eth/contracts/Reverts.sol b/src/chains/ethereum/tests/api/eth/contracts/Reverts.sol new file mode 100644 index 0000000000..14879bbf76 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/contracts/Reverts.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.4; + +contract Reverts { + function invalidRevertReason() public pure { + assembly { + // revert reason code + mstore(0x80, 0x0000000000000000000000000000000000000000000000000000000008c379a0) + // invalid data + mstore(0xA0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0) + // trigger revert, returning the mstore values set above + revert( + 0x9C, /* mem start */ + 0x24 /* mem length */ + ) + } + } +} diff --git a/src/chains/ethereum/tests/api/eth/eth.test.ts b/src/chains/ethereum/tests/api/eth/eth.test.ts new file mode 100644 index 0000000000..5de4379d33 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/eth.test.ts @@ -0,0 +1,497 @@ +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +import getProvider from "../../helpers/getProvider"; + +function hex(length: number) { + return `0x${Buffer.allocUnsafe(length).fill(0).toString("hex")}`; +} + +describe("api", () => { + describe("eth", () => { + let provider: EthereumProvider; + let accounts: string[]; + + beforeEach(async () => { + provider = await getProvider(); + accounts = await provider.send("eth_accounts"); + }); + + describe("eth_coinbase", () => { + it("should return correct address", async () => { + const coinbase = await provider.send("eth_coinbase"); + assert.strictEqual(coinbase, "0x" + "0".repeat(40)); + }); + }); + + describe("eth_mining", () => { + it("should return true", async () => { + const result = await provider.send("eth_mining"); + assert.strictEqual(result, true); + }); + }); + + describe("eth_syncing", () => { + it("should return true", async () => { + const result = await provider.send("eth_syncing"); + assert.strictEqual(result, false); + }); + }); + + describe("eth_hashrate", () => { + it("should return hashrate of zero", async () => { + const result = await provider.send("eth_hashrate"); + assert.deepStrictEqual(result, "0x0"); + }); + }); + + describe("eth_protocolVersion", () => { + it("should get ethereum version", async () => { + const result = await provider.send("eth_protocolVersion"); + assert.strictEqual(result, "0x3f", "Network Version should be 63"); + }); + }); + + describe("eth_getCompilers", () => { + it("should get compilers list", async () => { + const result = await provider.send("eth_getCompilers"); + assert.deepStrictEqual(result, []); + }); + }); + + describe("eth_submitWork", () => { + it("should get compilers list", async () => { + const result = await provider.send("eth_submitWork", [ + hex(8), + hex(32), + hex(32) + ]); + assert.deepStrictEqual(result, false); + }); + }); + + describe("eth_getWork", () => { + it("should get compilers list", async () => { + const result = await provider.send("eth_getWork", ["0x0"]); + assert.deepStrictEqual(result, []); + }); + }); + + describe("eth_submitHashrate", () => { + it("should return the status of eth_submitHashrate", async () => { + const result = await provider.send("eth_submitHashrate", [ + hex(32), + hex(32) + ]); + assert.deepStrictEqual(result, false); + }); + }); + + describe("eth_chainId", () => { + it("should return the default chain id", async () => { + const result = await provider.send("eth_chainId"); + assert.deepStrictEqual(result, "0x539"); + }); + + it("should use the default chain id when signing transactions", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + const txHash = await provider.send("eth_sendTransaction", [ + { from: accounts[0], to: accounts[0] } + ]); + await provider.once("message"); + const tx = await provider.send("eth_getTransactionByHash", [txHash]); + assert.strictEqual(tx.v, "0xa95"); + }); + + it("chainid option should change the chain id", async () => { + const provider = await getProvider({ chain: { chainId: 1234 } }); + const result = await provider.send("eth_chainId"); + assert.deepStrictEqual(result, "0x4d2"); + }); + }); + + describe("eth_getBalance", () => { + it("should return initial balance", async () => { + const balance = await provider.send("eth_getBalance", [accounts[0]]); + assert.strictEqual(balance, "0x56bc75e2d63100000"); + }); + + it("should return 0 for non-existent account", async () => { + const balance = await provider.send("eth_getBalance", [ + "0x1234567890123456789012345678901234567890" + ]); + assert.strictEqual(balance, "0x0"); + }); + }); + + describe("eth_getTransactionCount", () => { + it("should get the tranasction count of the block", async () => { + const tx = { + from: accounts[0], + to: accounts[1], + value: 1 + }; + + const txCount1 = await provider.send("eth_getTransactionCount", [ + accounts[0] + ]); + assert.strictEqual(txCount1, "0x0"); + const initialBlockNumber = await provider.send("eth_blockNumber"); + const txCount2 = await provider.send("eth_getTransactionCount", [ + accounts[0], + initialBlockNumber + ]); + assert.strictEqual(txCount2, "0x0"); + + await provider.send("eth_subscribe", ["newHeads"]); + + // send one tx, then check the count + await provider.send("miner_stop"); + await provider.send("eth_sendTransaction", [{ ...tx }]); + await provider.send("miner_start"); + const message1 = await provider.once("message"); + + const txCount3 = await provider.send("eth_getTransactionCount", [ + accounts[0], + message1.data.result.number + ]); + assert.strictEqual(txCount3, "0x1"); + + // send two txs, then check the count + await provider.send("miner_stop"); + await provider.send("eth_sendTransaction", [{ ...tx }]); + await provider.send("eth_sendTransaction", [{ ...tx }]); + await provider.send("miner_start"); + const message2 = await provider.once("message"); + + const txCount4 = await provider.send("eth_getTransactionCount", [ + accounts[0], + message2.data.result.number + ]); + assert.strictEqual(txCount4, "0x3"); + + // the check the count at different block numbers... + + const txCount5 = await provider.send("eth_getTransactionCount", [ + accounts[0], + message1.data.result.number + ]); + assert.strictEqual(txCount5, txCount3); + + const txCount6 = await provider.send("eth_getTransactionCount", [ + accounts[0], + initialBlockNumber + ]); + assert.strictEqual(txCount6, "0x0"); + + const txCount7 = await provider.send("eth_getTransactionCount", [ + accounts[0] + ]); + assert.strictEqual(txCount7, txCount4); + + const txCount8 = await provider.send("eth_getTransactionCount", [ + accounts[0], + "earliest" + ]); + assert.strictEqual(txCount8, "0x0"); + + const txCount9 = await provider.send("eth_getTransactionCount", [ + accounts[0], + "latest" + ]); + assert.strictEqual(txCount9, txCount4); + }); + }); + + describe("eth_blockNumber", () => { + it("should return initial block number of zero", async () => { + const blockNumber = await provider.send("eth_blockNumber"); + assert.strictEqual(parseInt(blockNumber, 10), 0); + }); + + it("should increment the block number after a transaction", async () => { + const tx = { + from: accounts[0], + to: accounts[1], + value: 1 + }; + + const startingBlockNumber = parseInt( + await provider.send("eth_blockNumber") + ); + await provider.send("eth_subscribe", ["newHeads"]); + await provider.send("eth_sendTransaction", [{ ...tx }]); + await provider.once("message"); + const blockx1 = await provider.send("eth_blockNumber"); + assert.strictEqual( + +blockx1, + startingBlockNumber + 1, + "first tx's block number not as expected" + ); + + const awaitFor = count => + new Promise(resolve => { + let counter = 0; + const off = provider.on("message", (_block: any) => { + counter++; + if (counter === count) { + off(); + resolve(void 0); + } + }); + }); + + let wait = awaitFor(4); + await Promise.all([ + provider.send("eth_sendTransaction", [{ ...tx }]), + provider.send("eth_sendTransaction", [{ ...tx }]), + provider.send("eth_sendTransaction", [{ ...tx }]), + provider.send("eth_sendTransaction", [{ ...tx }]) + ]); + + await Promise.all([ + provider.send("eth_sendTransaction", [{ ...tx }]), + provider.send("eth_sendTransaction", [{ ...tx }]), + provider.send("eth_sendTransaction", [{ ...tx }]), + provider.send("eth_sendTransaction", [{ ...tx }]) + ]); + await wait; + wait = awaitFor(4); + const blockx5 = await provider.send("eth_blockNumber"); + assert.strictEqual( + +blockx5, + startingBlockNumber + 5, + "second block's number not as expected" + ); + await wait; + const blockx9 = await provider.send("eth_blockNumber"); + assert.strictEqual( + +blockx9, + startingBlockNumber + 9, + "third block's number not as expected" + ); + }); + }); + + it("eth_getBlockByNumber", async () => { + const _subscriptionId = await provider.send("eth_subscribe", [ + "newHeads" + ]); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + const _message = await provider.once("message"); + const blocks = await Promise.all([ + provider.send("eth_getBlockByNumber", ["0x1", true]), + provider.send("eth_getBlockByNumber", ["0x1"]) + ]); + assert(blocks[0].hash, blocks[1].hash); + }); + + it("eth_getBlockByHash", async () => { + const _subscriptionId = await provider.send("eth_subscribe", [ + "newHeads" + ]); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + const _message = await provider.once("message"); + const block = await provider.send("eth_getBlockByNumber", ["0x1"]); + + const blocks = await Promise.all([ + provider.send("eth_getBlockByHash", [block.hash, true]), + provider.send("eth_getBlockByHash", [block.hash]) + ]); + assert(blocks[0].hash, blocks[1].hash); + const counts = await Promise.all([ + provider.send("eth_getBlockTransactionCountByNumber", ["0x1"]), + provider.send("eth_getBlockTransactionCountByHash", [blocks[0].hash]) + ]); + + assert(true); + }); + + it("eth_getBlockTransactionCountByHash", async () => { + const _subscriptionId = await provider.send("eth_subscribe", [ + "newHeads" + ]); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + const _message = await provider.once("message"); + const block = await provider.send("eth_getBlockByNumber", ["0x1"]); + + const count = await provider.send("eth_getBlockTransactionCountByHash", [ + block.hash + ]); + assert(count, "1"); + }); + + it("eth_getBlockTransactionCountByNumber", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + await provider.once("message"); + + const count = await provider.send( + "eth_getBlockTransactionCountByNumber", + ["0x1"] + ); + assert.strictEqual(count, "0x1"); + }); + + it("eth_sendTransaction bad data (tiny gas limit)", async () => { + await provider + .send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + gas: "0x01" + } + ]) + .catch(e => { + assert.strictEqual(e.code, -32000); + assert.strictEqual(e.message, "intrinsic gas too low"); + }); + }); + + it("eth_sendTransaction bad data (huge gas limit)", async () => { + await provider + .send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + gas: "0xfffffffff" + } + ]) + .catch(e => { + assert.strictEqual(e.code, -32000); + assert.strictEqual(e.message, "exceeds block gas limit"); + }); + }); + + it("handles block gas limit errors, callback style", done => { + provider.send( + { + jsonrpc: "2.0", + id: "1", + method: "eth_sendTransaction", + params: [ + { + from: accounts[0], + to: accounts[1], + gas: "0xfffffffff" // generates an "exceeds block gas limit" error + } + ] + }, + (e, r) => { + assert.strictEqual(e.message, "exceeds block gas limit"); + assert.strictEqual((r as any).error.code, -32000); + assert.strictEqual((r as any).error.message, e.message); + done(); + } + ); + }); + + it("eth_getTransactionByBlockNumberAndIndex", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + const txHash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + await provider.once("message"); + + const tx = await provider.send( + "eth_getTransactionByBlockNumberAndIndex", + ["0x1", "0x0"] + ); + assert.strictEqual( + tx.hash, + "0xab338178ffd130f1b7724a687ef20afcc75d44020184f82127ab1bc59f17d7e2", + "Unexpected transaction hash." + ); + assert.strictEqual( + tx.hash, + txHash, + "eth_getTransactionByBlockNumberAndIndex transaction hash doesn't match tx hash" + ); + }); + + it("eth_getTransactionByBlockHashAndIndex", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + const txHash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + const _message = await provider.once("message"); + const block = await provider.send("eth_getBlockByNumber", ["0x1"]); + + const tx = await provider.send("eth_getTransactionByBlockHashAndIndex", [ + block.hash, + "0x0" + ]); + assert.strictEqual( + tx.hash, + "0xab338178ffd130f1b7724a687ef20afcc75d44020184f82127ab1bc59f17d7e2", + "Unexpected transaction hash." + ); + assert.strictEqual( + tx.hash, + txHash, + "eth_getTransactionByBlockNumberAndIndex transaction hash doesn't match tx hash" + ); + }); + + it("eth_getTransactionReceipt", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + const hash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + const _message = await provider.once("message"); + + const receipt = await provider.send("eth_getTransactionReceipt", [hash]); + assert(receipt.transactionIndex, "0x0"); + }); + + it("eth_getTransactionByHash", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + const hash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + const _message = await provider.once("message"); + + const tx = await provider.send("eth_getTransactionByHash", [hash]); + assert(tx.transactionIndex, "0x0"); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/getCode.test.ts b/src/chains/ethereum/tests/api/eth/getCode.test.ts new file mode 100644 index 0000000000..7e8fc14d96 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/getCode.test.ts @@ -0,0 +1,97 @@ +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +import getProvider from "../../helpers/getProvider"; +import compile from "../../helpers/compile"; +import { join } from "path"; +import { Quantity } from "@ganache/utils"; + +describe("api", () => { + describe("eth", () => { + describe("getCode", () => { + describe("null checks", () => { + let provider: EthereumProvider; + + before(async () => { + provider = await getProvider(); + }); + + after(async () => { + provider && (await provider.disconnect()); + }); + + it("should return 0x for null address", async () => { + const code = await provider.send("eth_getCode", [ + "0x0000000000000000000000000000000000000000" + ]); + assert.strictEqual(code, "0x"); + }); + + it("should return 0x for un-initialized address", async () => { + const code = await provider.send("eth_getCode", [ + "0xabcdefg012345678abcdefg012345678abcdefg0" + ]); + assert.strictEqual(code, "0x"); + }); + + it("should return 0x for existing non-contract address", async () => { + const accounts = await provider.send("eth_accounts"); + const code = await provider.send("eth_getCode", [accounts[0]]); + assert.strictEqual(code, "0x"); + }); + }); + + describe("code checks", () => { + let provider: EthereumProvider; + let accounts: string[]; + let contractAddress: string; + let blockNumber: Quantity; + let contract: ReturnType; + + before(async () => { + contract = compile(join(__dirname, "./contracts/GetCode.sol")); + provider = await getProvider(); + accounts = await provider.send("eth_accounts"); + await provider.send("eth_subscribe", ["newHeads"]); + const transactionHash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + data: contract.code, + gas: 3141592 + } + ]); + await provider.once("message"); + const transactionReceipt = await provider.send( + "eth_getTransactionReceipt", + [transactionHash] + ); + contractAddress = transactionReceipt.contractAddress; + assert( + contractAddress !== null, + "Contract wasn't deployed as expected" + ); + + blockNumber = Quantity.from(transactionReceipt.blockNumber); + }); + + it("should return the code at the deployed block number", async () => { + const code = await provider.send("eth_getCode", [ + contractAddress, + blockNumber.toString() + ]); + assert.strictEqual( + code, + `0x${contract.contract.evm.deployedBytecode.object}` + ); + }); + + it("should return the no code at the previous block number", async () => { + const code = await provider.send("eth_getCode", [ + contractAddress, + Quantity.from(blockNumber.toBigInt() - 1n).toString() + ]); + assert.strictEqual(code, "0x"); + }); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/getStorageAt.test.ts b/src/chains/ethereum/tests/api/eth/getStorageAt.test.ts new file mode 100644 index 0000000000..c2afdd2522 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/getStorageAt.test.ts @@ -0,0 +1,94 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +import compile from "../../helpers/compile"; +import { join } from "path"; +import { Quantity } from "@ganache/utils"; +const THIRTY_TWO_BYES = "0".repeat(64); + +describe("api", () => { + describe("eth", () => { + describe("getStorageAt", () => { + let provider: EthereumProvider; + const contract = compile(join(__dirname, "./contracts/GetStorageAt.sol")); + let contractAddress: string; + let contractMethods: any; + + beforeEach(async () => { + provider = await getProvider({ + miner: { defaultTransactionGasLimit: 6721975 } + }); + const accounts = await provider.send("eth_accounts"); + const from = accounts[0]; + + await provider.send("eth_subscribe", ["newHeads"]); + + const transactionHash = await provider.send("eth_sendTransaction", [ + { + from, + data: contract.code + } + ]); + + await provider.once("message"); + + const receipt = await provider.send("eth_getTransactionReceipt", [ + transactionHash + ]); + + contractAddress = receipt.contractAddress; + contractMethods = contract.contract.evm.methodIdentifiers; + }); + + it("returns the value at the hex position", async () => { + const result = await provider.send("eth_getStorageAt", [ + contractAddress, + "0x0" + ]); + assert.strictEqual(BigInt(result), 123n); + const result2 = await provider.send("eth_getStorageAt", [ + contractAddress, + "0x1" + ]); + assert.strictEqual(result2, "0x01"); + }); + + it("returns the value at the 32-byte hex position", async () => { + const result = await provider.send("eth_getStorageAt", [ + contractAddress, + "0x" + THIRTY_TWO_BYES + ]); + assert.strictEqual(BigInt(result), 123n); + const result2 = await provider.send("eth_getStorageAt", [ + contractAddress, + "0x" + THIRTY_TWO_BYES.slice(-1) + "1" + ]); + assert.strictEqual(result2, "0x01"); + }); + + it("returns the value even when hex positions exceeds 32-bytes", async () => { + const thirtyThreeBytePosition = "0x1" + THIRTY_TWO_BYES; + const result = await provider.send("eth_getStorageAt", [ + contractAddress, + thirtyThreeBytePosition + ]); + assert.strictEqual(BigInt(result), 123n); + const thirtyThreeBytePosition2 = "0x" + THIRTY_TWO_BYES + "1"; + const result2 = await provider.send("eth_getStorageAt", [ + contractAddress, + thirtyThreeBytePosition2 + ]); + assert.strictEqual(result2, "0x01"); + }); + + it("rejects when the block doesn't exist", async () => { + await assert.rejects( + provider.send("eth_getStorageAt", [contractAddress, "0x0", "0x2"]), + { + message: "header not found" + } + ); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/legacyInstamining.test.ts b/src/chains/ethereum/tests/api/eth/legacyInstamining.test.ts new file mode 100644 index 0000000000..f7de64d197 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/legacyInstamining.test.ts @@ -0,0 +1,81 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; + +describe("api", () => { + describe("eth", () => { + describe("legacy", () => { + it("when not in legacy mode, does not mine before returning the tx hash", async () => { + const provider = await getProvider({ + miner: { legacyInstamine: false } + }); + const accounts = await provider.send("eth_accounts"); + + const hash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + const receipt = await provider.send("eth_getTransactionReceipt", [ + hash + ]); + assert.strictEqual(receipt, null); + }); + + it("when in legacy mode, mines before returns in the tx hash", async () => { + const provider = await getProvider({ + miner: { legacyInstamine: true } + }); + const accounts = await provider.send("eth_accounts"); + + const hash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + const receipt = await provider.send("eth_getTransactionReceipt", [ + hash + ]); + assert.notStrictEqual(receipt, null); + }); + + it("handles transaction balance errors, callback style", done => { + getProvider({ + miner: { legacyInstamine: true }, + chain: { vmErrorsOnRPCResponse: true } + }).then(async provider => { + const accounts = await provider.send("eth_accounts"); + + provider.send( + { + jsonrpc: "2.0", + id: "1", + method: "eth_sendTransaction", + params: [ + { + from: accounts[0], + to: accounts[1], + value: "0x76bc75e2d63100000" + } + ] + }, + (e, r) => { + assert( + e.message.includes( + "sender doesn't have enough funds to send tx" + ) + ); + assert.strictEqual(e.message, (r as any).error.message); + assert.strictEqual((r as any).error.code, -32000); + assert.strictEqual(typeof (r as any).error.data.result, "string"); + done(); + } + ); + }); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/logs.test.ts b/src/chains/ethereum/tests/api/eth/logs.test.ts new file mode 100644 index 0000000000..45e91fc742 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/logs.test.ts @@ -0,0 +1,488 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +import compile from "../../helpers/compile"; +import { join } from "path"; +import { promises } from "fs-extra"; + +describe("api", () => { + describe("eth", () => { + describe("logs", () => { + let provider: EthereumProvider; + let contract: ReturnType; + let contractAddress: string; + let accounts: string[]; + + beforeEach(async () => { + contract = compile(join(__dirname, "./contracts/Logs.sol")); + provider = await getProvider(); + accounts = await provider.send("eth_accounts"); + + const subscriptionId = await provider.send("eth_subscribe", [ + "newHeads" + ]); + const transactionHash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + data: contract.code, + gas: 3141592 + } + ]); + await provider.once("message"); + const transactionReceipt = await provider.send( + "eth_getTransactionReceipt", + [transactionHash] + ); + contractAddress = transactionReceipt.contractAddress; + await provider.send("eth_unsubscribe", [subscriptionId]); + }); + + describe("eth_subscribe", () => { + describe("logs", () => { + const onceMessageFor = subId => { + return new Promise(resolve => { + provider.on("message", message => { + if (message.data.subscription === subId) { + resolve(message); + } + }); + }); + }; + + it("subscribes and unsubscribes", async () => { + const subscriptionId = await provider.send("eth_subscribe", [ + "logs" + ]); + + assert(subscriptionId != null); + assert.notStrictEqual(subscriptionId, false); + + // subscribe again + const subscriptionId2 = await provider.send("eth_subscribe", [ + "logs" + ]); + + // trigger a log event, we should get two events + const numberOfLogs = 4; + const data = + "0x" + + contract.contract.evm.methodIdentifiers["logNTimes(uint8)"] + + numberOfLogs.toString().padStart(64, "0"); + const tx = { from: accounts[0], to: contractAddress, data }; + const subs = [ + onceMessageFor(subscriptionId), + onceMessageFor(subscriptionId2) + ]; + const txHash = await provider.send("eth_sendTransaction", [ + { ...tx } + ]); + + const [message1, message2] = await Promise.all(subs); + assert.deepStrictEqual(message1.data.result, message2.data.result); + + assert.strictEqual(message1.data.result.length, numberOfLogs); + + const unsubResult = await provider.send("eth_unsubscribe", [ + subscriptionId + ]); + assert.strictEqual(unsubResult, true); + await provider.send("eth_sendTransaction", [{ ...tx }]); + const message = await Promise.race([ + onceMessageFor(subscriptionId), + onceMessageFor(subscriptionId2) + ]); + assert.strictEqual( + message.data.subscription, + subscriptionId2, + "unsubscribe didn't work" + ); + }); + }); + }); + + describe("getLogs", () => { + it("should return a log for the constructor transaction", async () => { + const logs = await provider.send("eth_getLogs", [ + { address: contractAddress } + ]); + assert.strictEqual(logs.length, 1); + }); + + it("should return the logs", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + const numberOfLogs = 4; + const data = + "0x" + + contract.contract.evm.methodIdentifiers["logNTimes(uint8)"] + + numberOfLogs.toString().padStart(64, "0"); + const txHash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: contractAddress, + gas: 3141592, + data: data + } + ]); + await provider.once("message"); + const txReceipt = await provider.send("eth_getTransactionReceipt", [ + txHash + ]); + assert.deepStrictEqual(txReceipt.logs.length, numberOfLogs); + const logs = await provider.send("eth_getLogs", [ + { address: contractAddress } + ]); + assert.deepStrictEqual(logs, txReceipt.logs); + }); + + it("should filter out other blocks when using `latest`", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + const numberOfLogs = 4; + const data = + "0x" + + contract.contract.evm.methodIdentifiers["logNTimes(uint8)"] + + numberOfLogs.toString().padStart(64, "0"); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: contractAddress, + gas: 3141592, + data: data + } + ]); + await provider.once("message"); + await provider.send("evm_mine"); + await provider.once("message"); + const logs = await provider.send("eth_getLogs", [ + { address: contractAddress, toBlock: "latest", fromBlock: "latest" } + ]); + assert.strictEqual(logs.length, 0); + }); + + it("should filter appropriately when using fromBlock and toBlock", async () => { + const genesisBlockNumber = "0x0"; + const deployBlockNumber = "0x1"; + const emptyBlockNumber = "0x2"; + await provider.send("evm_mine"); // 0x2 + + await provider.send("eth_subscribe", ["newHeads"]); + const numberOfLogs = 4; + const data = + "0x" + + contract.contract.evm.methodIdentifiers["logNTimes(uint8)"] + + numberOfLogs.toString().padStart(64, "0"); + const txHash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: contractAddress, + gas: 3141592, + data: data + } + ]); // 0x3 + await provider.once("message"); + const { + blockNumber + } = await provider.send("eth_getTransactionReceipt", [txHash]); + + async function testGetLogs( + fromBlock: string, + toBlock: string, + expected: number, + address: string = contractAddress + ) { + const logs = await provider.send("eth_getLogs", [ + { address, fromBlock, toBlock } + ]); + assert.strictEqual( + logs.length, + expected, + `there should be ${expected} log(s) between the ${fromBlock} block and the ${toBlock} block` + ); + } + + // tests ranges up to latest/blockNumber + await testGetLogs("earliest", "earliest", 0); + await testGetLogs(genesisBlockNumber, genesisBlockNumber, 0); + await testGetLogs("earliest", emptyBlockNumber, 1); + await testGetLogs(genesisBlockNumber, emptyBlockNumber, 1); + await testGetLogs("earliest", "latest", numberOfLogs + 1); + await testGetLogs("earliest", blockNumber, numberOfLogs + 1); + await testGetLogs(genesisBlockNumber, "latest", numberOfLogs + 1); + await testGetLogs(genesisBlockNumber, blockNumber, numberOfLogs + 1); + await testGetLogs(deployBlockNumber, "latest", numberOfLogs + 1); + await testGetLogs(deployBlockNumber, blockNumber, numberOfLogs + 1); + await testGetLogs(emptyBlockNumber, "latest", numberOfLogs); + await testGetLogs(emptyBlockNumber, blockNumber, numberOfLogs); + + // tests variations where latest === blockNumber + await testGetLogs(blockNumber, blockNumber, numberOfLogs); + await testGetLogs(blockNumber, "latest", numberOfLogs); + await testGetLogs("latest", blockNumber, numberOfLogs); + await testGetLogs("latest", "latest", numberOfLogs); + + // mine an extra block + await provider.send("evm_mine"); // 0x3 + const lastBlockNumber = `0x${(parseInt(blockNumber) + 1).toString( + 16 + )}`; + await provider.once("message"); + + // test variations of `earliest` and `0x0` + await testGetLogs(genesisBlockNumber, genesisBlockNumber, 0); + await testGetLogs("earliest", "earliest", 0); + await testGetLogs("earliest", genesisBlockNumber, 0); + await testGetLogs(genesisBlockNumber, "earliest", 0); + + // test misc ranges not already tested + await testGetLogs(genesisBlockNumber, deployBlockNumber, 1); + await testGetLogs("earliest", deployBlockNumber, 1); + await testGetLogs("earliest", "latest", numberOfLogs + 1); + await testGetLogs(genesisBlockNumber, "latest", numberOfLogs + 1); + await testGetLogs(deployBlockNumber, "latest", numberOfLogs + 1); + // test variations involving the last block number + await testGetLogs( + genesisBlockNumber, + lastBlockNumber, + numberOfLogs + 1 + ); + await testGetLogs( + deployBlockNumber, + lastBlockNumber, + numberOfLogs + 1 + ); + await testGetLogs(emptyBlockNumber, lastBlockNumber, numberOfLogs); + await testGetLogs(lastBlockNumber, "latest", 0); + await testGetLogs("latest", lastBlockNumber, 0); + }); + + it("should filter appropriately when using blockHash", async () => { + const genesisBlockNumber = "0x0"; + const deployBlockNumber = "0x1"; + const emptyBlockNumber = "0x2"; + await provider.send("evm_mine"); // 0x2 + + await provider.send("eth_subscribe", ["newHeads"]); + const numberOfLogs = 4; + const data = + "0x" + + contract.contract.evm.methodIdentifiers["logNTimes(uint8)"] + + numberOfLogs.toString().padStart(64, "0"); + const txHash = await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: contractAddress, + gas: 3141592, + data: data + } + ]); // 0x3 + await provider.once("message"); + const { blockHash } = await provider.send( + "eth_getTransactionReceipt", + [txHash] + ); + + async function testGetLogs( + blockHash: string, + expected: number, + address: string = contractAddress + ) { + const logs = await provider.send("eth_getLogs", [ + { address, blockHash } + ]); + assert.strictEqual( + logs.length, + expected, + `there should be ${expected} log(s) at the ${blockHash} block` + ); + } + + // tests blockHash + let { + hash: genesisBlockHash + } = await provider.send("eth_getBlockByNumber", [genesisBlockNumber]); + await testGetLogs(blockHash, 4); + await testGetLogs(genesisBlockHash, 0); + let { + hash: deployBlockHash + } = await provider.send("eth_getBlockByNumber", [deployBlockNumber]); + await testGetLogs(deployBlockHash, 1, null); + let { + hash: emptyBlockHash + } = await provider.send("eth_getBlockByNumber", [emptyBlockNumber]); + await testGetLogs(emptyBlockHash, 0); + const invalidBlockHash = "0x123456789"; + await testGetLogs(invalidBlockHash, 0); + + // mine an extra block + await provider.send("evm_mine"); + await provider.once("message"); + + // make sure we still get the right data + await testGetLogs(blockHash, 4); + }); + }); + + describe("eth_newBlockFilter", () => { + it("returns new blocks", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + async function assertNoChanges() { + const noChanges = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(noChanges.length, 0); + } + const filterId = await provider.send("eth_newBlockFilter"); + await assertNoChanges(); + await provider.send("evm_mine"); + await provider.once("message"); + const changes1 = await provider.send("eth_getFilterChanges", [ + filterId + ]); + let blockNum = await provider.send("eth_blockNumber"); + let { hash } = await provider.send("eth_getBlockByNumber", [ + blockNum + ]); + assert.strictEqual(changes1[0], hash); + await assertNoChanges(); + await provider.send("evm_mine"); + await provider.once("message"); + blockNum = await provider.send("eth_blockNumber"); + let { hash: hash2 } = await provider.send("eth_getBlockByNumber", [ + blockNum + ]); + await provider.send("evm_mine"); + await provider.once("message"); + blockNum = await provider.send("eth_blockNumber"); + let { hash: hash3 } = await provider.send("eth_getBlockByNumber", [ + blockNum + ]); + + const changes2 = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(changes2[0], hash2); + assert.strictEqual(changes2[1], hash3); + await assertNoChanges(); + }); + }); + + describe("eth_newPendingTransactionFilter", () => { + it("returns new pending transactions", async () => { + await provider.send("eth_subscribe", ["newPendingTransactions"]); + async function assertNoChanges() { + const noChanges = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(noChanges.length, 0); + } + const filterId = await provider.send( + "eth_newPendingTransactionFilter" + ); + const tx = { from: accounts[0], to: accounts[0] }; + await assertNoChanges(); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash = await provider.once("message"); + const changes1 = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(changes1[0], hash.data.result); + await assertNoChanges(); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash2 = await provider.once("message"); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash3 = await provider.once("message"); + + const changes2 = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(changes2[0], hash2.data.result); + assert.strictEqual(changes2[1], hash3.data.result); + await assertNoChanges(); + }); + }); + + describe("eth_newFilter", () => { + it("returns new logs", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + async function assertNoChanges() { + const noChanges = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(noChanges.length, 0); + } + const filterId = await provider.send("eth_newFilter"); + const numberOfLogs = 1; + const data = + "0x" + + contract.contract.evm.methodIdentifiers["logNTimes(uint8)"] + + numberOfLogs.toString().padStart(64, "0"); + const tx = { from: accounts[0], to: contractAddress, data }; + await assertNoChanges(); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash = await provider.once("message"); + const changes1 = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(changes1.length, 1); + await assertNoChanges(); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash2 = await provider.once("message"); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash3 = await provider.once("message"); + + const changes2 = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(changes2.length, 2); + await assertNoChanges(); + }); + }); + + describe("eth_newFilter", () => { + it("returns new logs", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + async function assertNoChanges() { + const noChanges = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(noChanges.length, 0); + } + const currentBlockNumber = + "0x" + + (parseInt(await provider.send("eth_blockNumber")) + 1).toString(16); + const filterId = await provider.send("eth_newFilter", [ + { fromBlock: currentBlockNumber, toBlock: "0x99" } + ]); + const numberOfLogs = 1; + const data = + "0x" + + contract.contract.evm.methodIdentifiers["logNTimes(uint8)"] + + numberOfLogs.toString().padStart(64, "0"); + const tx = { from: accounts[0], to: contractAddress, data }; + await assertNoChanges(); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash = await provider.once("message"); + const changes1 = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(changes1.length, 1); + await assertNoChanges(); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash2 = await provider.once("message"); + provider.send("eth_sendTransaction", [{ ...tx }]); + let hash3 = await provider.once("message"); + + const changes2 = await provider.send("eth_getFilterChanges", [ + filterId + ]); + assert.strictEqual(changes2.length, 2); + await assertNoChanges(); + + const allChanges = await provider.send("eth_getFilterLogs", [ + filterId + ]); + assert.deepStrictEqual(allChanges, [...changes1, ...changes2]); + }); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/sendRawTransaction.test.ts b/src/chains/ethereum/tests/api/eth/sendRawTransaction.test.ts new file mode 100644 index 0000000000..ec60545620 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/sendRawTransaction.test.ts @@ -0,0 +1,61 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +import Transaction from "ethereumjs-tx/dist/transaction"; +import Common from "ethereumjs-common"; + +describe("api", () => { + describe("eth", () => { + describe("eth_sendRawTransaction*", () => { + let secretKey = + "0x4c3fc38239e503913706205746ef2dcc54a5ea9971988bfcac136b43e3190841"; + let provider: EthereumProvider; + let accounts: string[]; + const common = Common.forCustomChain( + "mainnet", + { + name: "ganache", + chainId: 1337, + comment: "Local test network", + bootstrapNodes: [] + }, + "petersburg" + ); + + beforeEach(async () => { + provider = await getProvider({ + wallet: { + mnemonic: "sweet treat", + accounts: [{ secretKey, balance: "0xffffff" }] + } + }); + accounts = await provider.send("eth_accounts"); + }); + + it("processes a signed transaction", async () => { + const transaction = new Transaction( + { + value: "0xff", + gasLimit: "0x33450", + to: accounts[0] + }, + { common } + ); + + const secretKeyBuffer = Buffer.from(secretKey.substr(2), "hex"); + transaction.sign(secretKeyBuffer); + + await provider.send("eth_subscribe", ["newHeads"]); + const txHash = await provider.send("eth_sendRawTransaction", [ + transaction.serialize() + ]); + await provider.once("message"); + + const receipt = await provider.send("eth_getTransactionReceipt", [ + txHash + ]); + assert.strictEqual(receipt.transactionHash, txHash); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/sendTransaction.test.ts b/src/chains/ethereum/tests/api/eth/sendTransaction.test.ts new file mode 100644 index 0000000000..50c518b3c6 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/sendTransaction.test.ts @@ -0,0 +1,103 @@ +import assert from "assert"; +import getProvider from "../../helpers/getProvider"; +import compile from "../../helpers/compile"; +import { join } from "path"; +import EthereumProvider from "../../../src/provider"; +import { EthereumProviderOptions } from "../../../src/options"; + +describe("api", () => { + describe("eth", () => { + describe("sendTransaction", () => { + describe("contracts", () => { + describe("revert", () => { + async function deployContract( + provider: EthereumProvider, + accounts: string[] + ) { + const contract = compile( + join(__dirname, "./contracts/Reverts.sol") + ); + + const from = accounts[0]; + + await provider.send("eth_subscribe", ["newHeads"]); + + const transactionHash = await provider.send("eth_sendTransaction", [ + { + from, + data: contract.code, + gas: 3141592 + } + ]); + + await provider.once("message"); + + const receipt = await provider.send("eth_getTransactionReceipt", [ + transactionHash + ]); + assert.strictEqual(receipt.blockNumber, "0x1"); + + const contractAddress = receipt.contractAddress; + return { + contract, + contractAddress + }; + } + + it("doesn't crash on badly encoded revert string", async () => { + async function test(opts: EthereumProviderOptions) { + const provider = await getProvider(opts); + const accounts = await provider.send("eth_accounts"); + const { contract, contractAddress } = await deployContract( + provider, + accounts + ); + const contractMethods = contract.contract.evm.methodIdentifiers; + const prom = provider.send("eth_call", [ + { + from: accounts[0], + to: contractAddress, + data: "0x" + contractMethods["invalidRevertReason()"] + } + ]); + + const revertString = + "0x08c379a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0"; + if (opts.chain.vmErrorsOnRPCResponse) { + const result = await prom.catch(e => e); + assert.strictEqual( + result.code, + -32000, + "Error code should be -32000" + ); + assert.strictEqual( + result.data.reason, + null, + "The reason is undecodable, and thus should be null" + ); + assert.strictEqual( + result.data.message, + "revert", + "The message should not have a reason string included" + ); + assert.strictEqual( + result.data.result, + revertString, + "The revert reason should be encoded as hex" + ); + } else { + assert.strictEqual( + await prom, + revertString, + "The revert reason should be encoded as hex" + ); + } + } + await test({ chain: { vmErrorsOnRPCResponse: false } }); + await test({ chain: { vmErrorsOnRPCResponse: true } }); + }); + }); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/sign.test.ts b/src/chains/ethereum/tests/api/eth/sign.test.ts new file mode 100644 index 0000000000..be8db14351 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/sign.test.ts @@ -0,0 +1,91 @@ +import assert from "assert"; +import { + ecrecover, + pubToAddress, + fromSigned, + hashPersonalMessage +} from "ethereumjs-util"; +import getProvider from "../../helpers/getProvider"; +import { Data } from "@ganache/utils"; + +describe("api", () => { + describe("eth", () => { + describe("sign", () => { + let accounts; + let provider; + + // Load account. + before(async () => { + // This account produces an edge case signature when it signs the hex-encoded buffer: + // '0x07091653daf94aafce9acf09e22dbde1ddf77f740f9844ac1f0ab790334f0627'. (See Issue #190) + const acc = { + balance: "0x0", + secretKey: + "0xe6d66f02cd45a13982b99a5abf3deab1f67cf7be9fee62f0a072cb70896342e4" + }; + provider = await getProvider({ + wallet: { + accounts: [acc] + } + }); + accounts = await provider.send("eth_accounts"); + }); + + it("should produce a signature whose signer can be recovered", async () => { + const msg = Buffer.from("0xffffffffff"); + const msgHash = hashPersonalMessage(msg); + + const address = accounts[0]; + let sgn = await provider.send("eth_sign", [ + address, + Data.from(msg).toString() + ]); + sgn = sgn.slice(2); + + const r = Buffer.from(sgn.slice(0, 64), "hex"); + const s = Buffer.from(sgn.slice(64, 128), "hex"); + const v = parseInt(sgn.slice(128), 16); + const pub = ecrecover( + msgHash, + v, + r, + s, + provider.getOptions().chain.chainId + ); + const addr = fromSigned(pubToAddress(pub)); + const strAddr = "0x" + addr.toString("hex"); + assert.strictEqual(strAddr, accounts[0].toLowerCase()); + }); + + it("should work if ecsign produces 'r' or 's' components that start with 0", async () => { + // This message produces a zero prefixed 'r' component when signed by + // ecsign w/ the account set in this test's 'before' block. + const msgHex = + "0x07091653daf94aafce9acf09e22dbde1ddf77f740f9844ac1f0ab790334f0627"; + const edgeCaseMsg = Data.from(msgHex).toBuffer(); + const msgHash = hashPersonalMessage(edgeCaseMsg); + + let sgn = await provider.send("eth_sign", [accounts[0], msgHex]); + sgn = sgn.slice(2); + + const r = Buffer.from(sgn.slice(0, 64), "hex"); + const s = Buffer.from(sgn.slice(64, 128), "hex"); + const v = parseInt(sgn.slice(128), 16); + const pub = ecrecover( + msgHash, + v, + r, + s, + provider.getOptions().chain.chainId + ); + const addr = fromSigned(pubToAddress(pub)); + const strAddr = "0x" + addr.toString("hex"); + assert.deepStrictEqual(strAddr, accounts[0].toLowerCase()); + }); + + after("shutdown", async () => { + provider && (await provider.disconnect()); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/signTypedData.test.ts b/src/chains/ethereum/tests/api/eth/signTypedData.test.ts new file mode 100644 index 0000000000..8463e12088 --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/signTypedData.test.ts @@ -0,0 +1,138 @@ +import assert from "assert"; +const createKeccakHash = require("keccak"); +import getProvider from "../../helpers/getProvider"; + +describe("api", () => { + describe("eth", () => { + describe("signTypedData", () => { + let accounts; + let provider; + + // Load account. + before(async () => { + // Account based on https://github.com/ethereum/EIPs/blob/master/assets/eip-712/Example.js + const acc = { + balance: "0x0", + secretKey: createKeccakHash("keccak256").update("cow").digest() + }; + provider = await getProvider({ + wallet: { + accounts: [acc] + } + }); + accounts = await provider.send("eth_accounts"); + }); + + it("should produce a signature whose signer can be recovered", async () => { + const typedData = { + types: { + EIP712Domain: [ + { name: "name", type: "string" }, + { name: "version", type: "string" }, + { name: "chainId", type: "uint256" }, + { name: "verifyingContract", type: "address" } + ], + Person: [ + { name: "name", type: "string" }, + { name: "wallet", type: "address" } + ], + Mail: [ + { name: "from", type: "Person" }, + { name: "to", type: "Person" }, + { name: "contents", type: "string" } + ] + }, + primaryType: "Mail", + domain: { + name: "Ether Mail", + version: "1", + chainId: 1, + verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + message: { + from: { + name: "Cow", + wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + to: { + name: "Bob", + wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + contents: "Hello, Bob!" + } + }; + + const result = await provider.send("eth_signTypedData", [ + accounts[0], + typedData + ]); + assert.strictEqual( + result, + "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c" + ); + }); + + it("should produce a signature whose signer can be recovered (for arrays)", async () => { + const typedData = { + types: { + EIP712Domain: [ + { name: "name", type: "string" }, + { name: "version", type: "string" }, + { name: "chainId", type: "uint256" }, + { name: "verifyingContract", type: "address" } + ], + Person: [ + { name: "name", type: "string" }, + { name: "wallets", type: "address[]" } + ], + Mail: [ + { name: "from", type: "Person" }, + { name: "to", type: "Person[]" }, + { name: "contents", type: "string" } + ], + Group: [ + { name: "name", type: "string" }, + { name: "members", type: "Person[]" } + ] + }, + domain: { + name: "Ether Mail", + version: "1", + chainId: 1, + verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + primaryType: "Mail", + message: { + from: { + name: "Cow", + wallets: [ + "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF" + ] + }, + to: [ + { + name: "Bob", + wallets: [ + "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", + "0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57", + "0xB0B0b0b0b0b0B000000000000000000000000000" + ] + } + ], + contents: "Hello, Bob!" + } + }; + + const result = await provider.send("eth_signTypedData", [ + accounts[0], + typedData + ]); + assert.strictEqual( + result, + "0x65cbd956f2fae28a601bebc9b906cea0191744bd4c4247bcd27cd08f8eb6b71c78efdf7a31dc9abee78f492292721f362d296cf86b4538e07b51303b67f749061b" + ); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/subscribe.test.ts b/src/chains/ethereum/tests/api/eth/subscribe.test.ts new file mode 100644 index 0000000000..1a326693da --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/subscribe.test.ts @@ -0,0 +1,201 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +import { Quantity } from "@ganache/utils"; + +describe("api", () => { + describe("eth", () => { + describe("eth_subscribe*", () => { + let provider: EthereumProvider; + let accounts: string[]; + const gasLimit = "0x6691b7"; + const time = new Date("2019/03/15 GMT"); + + beforeEach(async () => { + provider = await getProvider({ + chain: { + time + }, + miner: { + blockGasLimit: gasLimit + }, + wallet: { + mnemonic: "sweet treat" + } + }); + accounts = await provider.send("eth_accounts"); + }); + + describe("newHeads", () => { + it("subscribes and unsubscribes", async () => { + const timestamp = ((+time / 1000) | 0) + 1; + const startingBlockNumber = parseInt( + await provider.send("eth_blockNumber") + ); + const subscriptionId = await provider.send("eth_subscribe", [ + "newHeads" + ]); + + assert(subscriptionId != null); + assert.notStrictEqual(subscriptionId, false); + + // subscribe again + const subscriptionId2 = await provider.send("eth_subscribe", [ + "newHeads" + ]); + + // trigger a mine, we should get two events + await provider.send("evm_mine", [timestamp]); + let counter = 0; + + const message = await new Promise(resolve => { + let firstMessage; + provider.on("message", (message: any) => { + counter++; + if (counter === 1) { + firstMessage = message; + } + if (counter === 2) { + assert.deepStrictEqual( + firstMessage.data.result, + message.data.result + ); + resolve(firstMessage); + } + }); + }); + + assert.deepStrictEqual(message, { + type: "eth_subscription", + data: { + result: { + difficulty: "0x0", + extraData: "0x", + gasLimit: gasLimit, + gasUsed: "0x0", + hash: + "0xf821422e084d82d550019e555b656b9113c9af45c4c03fad670caaa9b5d8acde", + logsBloom: `0x${"0".repeat(512)}`, + miner: `0x${"0".repeat(40)}`, + mixHash: `0x${"0".repeat(64)}`, + nonce: "0x0000000000000000", + number: Quantity.from(startingBlockNumber + 1).toString(), + parentHash: + "0x746144f35cfbcc1bb8ea1dcd540b674c81cc25ffec8fa1ec42d444cba9678cc2", + receiptsRoot: + "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + sha3Uncles: + "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + stateRoot: + "0x8281cb204e0242d2d9178e392b60eaf4563ae5ffc4897c9c6cf6e99a4d35aff3", + timestamp: Quantity.from(timestamp).toString(), + transactionsRoot: + "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, + subscription: subscriptionId + } + }); + + // trigger a mine... we should only get a _single_ message this time + const unsubResult = await provider.send("eth_unsubscribe", [ + subscriptionId + ]); + assert.strictEqual(unsubResult, true); + await provider.send("evm_mine", [timestamp]); + await assert.doesNotReject( + new Promise((resolve, reject) => { + provider.on("message", async (message: any) => { + if (subscriptionId2 === message.data.subscription) { + const blockNumber = parseInt( + await provider.send("eth_blockNumber") + ); + assert.strictEqual(blockNumber, startingBlockNumber + 2); + + resolve(void 0); + } else { + reject(new Error("Unsubscribe didn't work!")); + } + }); + }) + ); + }); + }); + + describe("newPendingTransactions", () => { + it("subscribes and unsubscribes", async () => { + const subscriptionId = await provider.send("eth_subscribe", [ + "newPendingTransactions" + ]); + + assert(subscriptionId != null); + assert.notStrictEqual(subscriptionId, false); + + // subscribe again + const subscriptionId2 = await provider.send("eth_subscribe", [ + "newPendingTransactions" + ]); + + let messagePromise = new Promise(resolve => { + let firstMessage; + provider.on("message", (message: any) => { + counter++; + if (counter === 1) { + firstMessage = message; + } + if (counter === 2) { + assert.deepStrictEqual( + firstMessage.data.result, + message.data.result + ); + resolve(firstMessage); + } + }); + }); + + // trigger a pendingTransaction, we should get two events + const tx = { from: accounts[0], to: accounts[0] }; + const txHash = await provider.send("eth_sendTransaction", [ + { ...tx } + ]); + let counter = 0; + + const message = await messagePromise; + + assert.deepStrictEqual(message, { + type: "eth_subscription", + data: { + result: txHash, + subscription: subscriptionId + } + }); + + // trigger a mine... we should only get a _single_ message this time + const unsubResult = await provider.send("eth_unsubscribe", [ + subscriptionId + ]); + assert.strictEqual(unsubResult, true); + messagePromise = new Promise((resolve, reject) => { + provider.on("message", async (message: any) => { + if (subscriptionId2 === message.data.subscription) { + assert.strictEqual(message.data.result, txHash2); + + resolve(message.data.result); + } else { + reject(new Error("Unsubscribe didn't work!")); + } + }); + }); + const txHash2 = await provider.send("eth_sendTransaction", [ + { ...tx } + ]); + await assert.doesNotReject(messagePromise); + }); + }); + + it("returns false for unsubscribe with bad id", async () => { + const unsubResult = await provider.send("eth_unsubscribe", ["0xffff"]); + assert.strictEqual(unsubResult, false); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/eth/uncles.test.ts b/src/chains/ethereum/tests/api/eth/uncles.test.ts new file mode 100644 index 0000000000..5ee221542a --- /dev/null +++ b/src/chains/ethereum/tests/api/eth/uncles.test.ts @@ -0,0 +1,89 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; + +describe("api", () => { + describe("eth", () => { + describe("eth_getUncle*", () => { + let provider: EthereumProvider; + let accounts: string[]; + + beforeEach(async () => { + provider = await getProvider(); + accounts = await provider.send("eth_accounts"); + }); + + it("eth_getUncleCountByBlockHash", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + await provider.once("message"); + const block = await provider.send("eth_getBlockByNumber", ["0x1"]); + + const count = await provider.send("eth_getUncleCountByBlockHash", [ + block.hash + ]); + assert.strictEqual(count, "0x0"); + }); + + it("eth_getUncleCountByBlockNumber", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + await provider.once("message"); + + const count = await provider.send("eth_getUncleCountByBlockNumber", [ + "0x1" + ]); + assert.strictEqual(count, "0x0"); + }); + + it("eth_getUncleByBlockHashAndIndex", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + await provider.once("message"); + const block = await provider.send("eth_getBlockByNumber", ["0x1"]); + + const result = await provider.send("eth_getUncleByBlockHashAndIndex", [ + block.hash, + "0x0" + ]); + assert.deepStrictEqual(result, null); + }); + + it("eth_getUncleByBlockNumberAndIndex", async () => { + await provider.send("eth_subscribe", ["newHeads"]); + await provider.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + await provider.once("message"); + + const result = await provider.send( + "eth_getUncleByBlockNumberAndIndex", + ["0x1", "0x0"] + ); + assert.deepStrictEqual(result, null); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/evm/evm.test.ts b/src/chains/ethereum/tests/api/evm/evm.test.ts new file mode 100644 index 0000000000..0b824229ee --- /dev/null +++ b/src/chains/ethereum/tests/api/evm/evm.test.ts @@ -0,0 +1,245 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import { Quantity } from "@ganache/utils"; +import EthereumProvider from "../../../src/provider"; + +function between(x: number, min: number, max: number) { + return x >= min && x <= max; +} + +describe("api", () => { + describe("evm", () => { + describe("evm_setTime", () => { + it("should set the time correctly when difference is greater than 2**31", async () => { + // this test is here to prevent a dev from "optimizing" rounding to use + // bitwise tricks since those won't work on numbers greater than 2**31. + + const provider = await getProvider(); + const bin32 = 2 ** 31; + const now = Date.now(); + // fast forward time by bin32, plus 2 seconds, in case testing is slow + const newTime = bin32 + now + 2; + + const timeAdjustment = await provider.send("evm_setTime", [newTime]); + + // it should return `newTime - now`, floored to the nearest second + const baseLineOffset = Math.floor((newTime - now) / 1000); + assert(between(timeAdjustment, baseLineOffset - 2, baseLineOffset + 2)); + }); + + it("should set the time correctly when given as a hex string", async () => { + const provider = await getProvider(); + const now = Date.now(); + // fast forward time by 10 seconds (plus 2 seconds in case testing is slow) + const newTime = now + 10000 + 2000; + + const timeAdjustment = await provider.send("evm_setTime", [ + `0x${newTime.toString(16)}` + ]); + + // it should return `newTime - now`, floored to the nearest second + const baseLineOffset = Math.floor((newTime - now) / 1000); + assert(between(timeAdjustment, baseLineOffset - 2, baseLineOffset + 2)); + }); + + it("should set the time correctly when given as a Date", async () => { + const provider = await getProvider(); + const now = Date.now(); + // fast forward time by 10 seconds (plus 2 seconds in case testing is slow), then create a new Date object + const newTime = new Date(now + 10000 + 2000); + + const timeAdjustment = await provider.send("evm_setTime", [newTime]); + + // it should return `newTime.getTime() - now`, floored to the nearest second + const baseLineOffset = Math.floor((newTime.getTime() - now) / 1000); + assert(between(timeAdjustment, baseLineOffset - 2, baseLineOffset + 2)); + }); + }); + + describe("evm_increaseTime", () => { + it("should return the `timeAdjustment` value via `evm_increaseTime` when provided as a number", async () => { + const provider = await getProvider(); + const seconds = 10; + const timeAdjustment = await provider.send("evm_increaseTime", [ + seconds + ]); + assert.strictEqual(timeAdjustment, seconds); + }); + + it("should return the `timeAdjustment` value via `evm_increaseTime` when provided as hex string", async () => { + const provider = await getProvider(); + const seconds = 10; + const timeAdjustment = await provider.send("evm_increaseTime", [ + `0x${seconds.toString(16)}` + ]); + assert.strictEqual(timeAdjustment, seconds); + }); + }); + + describe("evm_mine", () => { + it("should mine a block on demand", async () => { + const provider = await getProvider(); + const initialBlock = parseInt(await provider.send("eth_blockNumber")); + await provider.send("evm_mine"); + const currentBlock = parseInt(await provider.send("eth_blockNumber")); + assert.strictEqual(currentBlock, initialBlock + 1); + }); + + it("should mine a block on demand at the specified timestamp", async () => { + const startDate = new Date(2019, 3, 15); + const miningTimestamp = Math.floor( + new Date(2020, 3, 15).getTime() / 1000 + ); + const provider = await getProvider({ chain: { time: startDate } }); + await provider.send("evm_mine", [miningTimestamp]); + const currentBlock = await provider.send("eth_getBlockByNumber", [ + "latest" + ]); + assert.strictEqual(parseInt(currentBlock.timestamp), miningTimestamp); + }); + + it("should mine a block even when mining is stopped", async () => { + const provider = await getProvider(); + const initialBlock = parseInt(await provider.send("eth_blockNumber")); + await provider.send("miner_stop"); + await provider.send("evm_mine"); + const currentBlock = parseInt(await provider.send("eth_blockNumber")); + assert.strictEqual(currentBlock, initialBlock + 1); + }); + + it("should mine a block when in interval mode", async () => { + const provider = await getProvider({ miner: { blockTime: 1000 } }); + const initialBlock = parseInt(await provider.send("eth_blockNumber")); + await provider.send("evm_mine"); + const currentBlock = parseInt(await provider.send("eth_blockNumber")); + assert.strictEqual(currentBlock, initialBlock + 1); + }); + + it("should mine a block when in interval mode even when mining is stopped", async () => { + const provider = await getProvider({ miner: { blockTime: 1000 } }); + const initialBlock = parseInt(await provider.send("eth_blockNumber")); + await provider.send("miner_stop"); + await provider.send("evm_mine"); + const currentBlock = parseInt(await provider.send("eth_blockNumber")); + assert.strictEqual(currentBlock, initialBlock + 1); + }); + }); + + describe("evm_setAccountNonce", () => { + it("should set the nonce forward", async () => { + const provider = await getProvider(); + const [account] = await provider.send("eth_accounts"); + const newCount = Quantity.from(1000); + const initialCount = parseInt( + await provider.send("eth_getTransactionCount", [account]) + ); + assert.strictEqual(initialCount, 0); + const status = await provider.send("evm_setAccountNonce", [ + account, + newCount.toString() + ]); + assert.strictEqual(status, true); + const afterCount = parseInt( + await provider.send("eth_getTransactionCount", [account]) + ); + assert.strictEqual(afterCount, newCount.toNumber()); + }); + }); + + describe("evm_lockUnknownAccount/evm_unlockUnknownAccount", () => { + let accounts: string[], provider: EthereumProvider; + before(async () => { + provider = await getProvider(); + accounts = await provider.send("eth_accounts"); + }); + + it("should unlock any account after server has been started", async () => { + const address = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"; + const result1 = await provider.send("evm_unlockUnknownAccount", [ + address + ]); + assert.strictEqual(result1, true); + + // should return `false` if account was already locked + const result2 = await provider.send("evm_unlockUnknownAccount", [ + address + ]); + assert.strictEqual(result2, false); + }); + + it("should not unlock any locked personal account", async () => { + const [address] = accounts; + await provider.send("personal_lockAccount", [address]); + try { + await assert.rejects( + provider.send("evm_unlockUnknownAccount", [ + { + message: "cannot unlock known/personal account" + } + ]) + ); + } finally { + // unlock the account + await provider.send("personal_unlockAccount", [address, "", 0]); + } + }); + + it("should lock any unlocked unknown account via evm_lockUnknownAccount", async () => { + const address = "0x842d35Cc6634C0532925a3b844Bc454e4438f44f"; + const unlockResult = await provider.send("evm_unlockUnknownAccount", [ + address + ]); + assert.strictEqual(unlockResult, true); + + const lockResult1 = await provider.send("evm_lockUnknownAccount", [ + address + ]); + assert.strictEqual(lockResult1, true); + + // bonus: also make sure we return false when the account is already locked: + const lockResult2 = await provider.send("evm_lockUnknownAccount", [ + address + ]); + assert.strictEqual(lockResult2, false); + }); + + it("should not lock a known account via evm_lockUnknownAccount", async () => { + await assert.rejects( + provider.send("evm_lockUnknownAccount", [accounts[0]]), + { + message: "cannot lock known/personal account" + } + ); + }); + + it("should not lock a personal account via evm_lockUnknownAccount", async () => { + // create a new personal account + const address = await provider.send("personal_newAccount", [ + "password" + ]); + + // then explicitly unlock it + const result = await provider.send("personal_unlockAccount", [ + address, + "password", + 0 + ]); + assert.strictEqual(result, true); + + // then try to lock it via evm_lockUnknownAccount + await assert.rejects( + provider.send("evm_lockUnknownAccount", [address]), + { + message: "cannot lock known/personal account" + } + ); + }); + + it("should return `false` upon lock if account isn't locked (unknown account)", async () => { + const address = "0x942d35Cc6634C0532925a3b844Bc454e4438f450"; + const result = await provider.send("evm_lockUnknownAccount", [address]); + assert.strictEqual(result, false); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/evm/snapshot.sol b/src/chains/ethereum/tests/api/evm/snapshot.sol new file mode 100644 index 0000000000..158cf5414d --- /dev/null +++ b/src/chains/ethereum/tests/api/evm/snapshot.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.4; + +contract snapshot { + uint256 public n = 42; + + function inc() public { + n += 1; + } +} diff --git a/src/chains/ethereum/tests/api/evm/snapshot.test.ts b/src/chains/ethereum/tests/api/evm/snapshot.test.ts new file mode 100644 index 0000000000..5d72ba744b --- /dev/null +++ b/src/chains/ethereum/tests/api/evm/snapshot.test.ts @@ -0,0 +1,561 @@ +import assert from "assert"; +import { join } from "path"; +import getProvider from "../../helpers/getProvider"; +import compile from "../../helpers/compile"; + +const eth = "0x" + 1000000000000000000n.toString(16); + +describe("api", () => { + describe("evm", () => { + describe("snapshot / revert", () => { + let context = {} as any; + let startingBalance; + let snapshotId; + + beforeEach("Set up provider and deploy a contract", async () => { + const contract = compile(join(__dirname, "./snapshot.sol")); + + const p = await getProvider({ + miner: { defaultTransactionGasLimit: 6721975 } + }); + const accounts = await p.send("eth_accounts"); + const from = accounts[3]; + + await p.send("eth_subscribe", ["newHeads"]); + + const transactionHash = await p.send("eth_sendTransaction", [ + { + from, + data: contract.code + } + ]); + + await p.once("message"); + + const receipt = await p.send("eth_getTransactionReceipt", [ + transactionHash + ]); + assert.strictEqual(receipt.blockNumber, "0x1"); + + const to = receipt.contractAddress; + const methods = contract.contract.evm.methodIdentifiers; + + context.send = p.send.bind(p); + context.accounts = accounts; + context.provider = p; + context.instance = { + n: () => { + const tx = { + to, + data: "0x" + methods["n()"] + }; + return p.send("eth_call", [tx]); + }, + inc: async (tx: any) => { + tx.from ||= accounts[0]; + tx.to = to; + tx.data = "0x" + methods["inc()"]; + const hash = await p.send("eth_sendTransaction", [tx]); + await p.once("message"); + return await p.send("eth_getTransactionByHash", [hash]); + } + }; + }); + + beforeEach("send a transaction then make a checkpoint", async () => { + const { accounts, send, provider } = context; + + await send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: eth, + gas: 90000 + } + ]); + + await provider.once("message"); + + // Since transactions happen immediately, we can assert the balance. + let balance = await send("eth_getBalance", [accounts[0]]); + balance = BigInt(balance); + + // Assert the starting balance is where we think it is, including tx costs. + assert( + balance > 98900000000000000000 && balance < 99000000000000000000 + ); + startingBalance = balance; + + // Now checkpoint. + snapshotId = await send("evm_snapshot"); + }); + + it("rolls back successfully", async () => { + const { accounts, send, provider } = context; + + // Send another transaction, check the balance, then roll it back to the old one and check the balance again. + const transactionHash = await send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: eth, + gas: 90000 + } + ]); + + await provider.once("message"); + + let balance = await send("eth_getBalance", [accounts[0]]); + balance = BigInt(balance); + + // Assert the starting balance is where we think it is, including tx costs. + assert( + balance > 97900000000000000000n && balance < 98000000000000000000n + ); + + const status = await send("evm_revert", [snapshotId]); + + assert(status, "Snapshot should have returned true"); + + let revertedBalance = await send("eth_getBalance", [accounts[0]]); + revertedBalance = BigInt(revertedBalance); + + assert( + revertedBalance === startingBalance, + "Should have reverted back to the starting balance" + ); + + const oldReceipt = await send("eth_getTransactionReceipt", [ + transactionHash + ]); + assert.strictEqual( + oldReceipt, + null, + "Receipt should be null as it should have been removed" + ); + }); + + it("returns false when reverting a snapshot that doesn't exist", async () => { + const { send } = context; + + const snapShotId1 = await send("evm_snapshot"); + const snapShotId2 = await send("evm_snapshot"); + const response1 = await send("evm_revert", [snapShotId1]); + assert.strictEqual( + response1, + true, + "Reverting a snapshot that exists does not work" + ); + const response2 = await send("evm_revert", [snapShotId2]); + assert.strictEqual( + response2, + false, + "Reverting a snapshot that no longer exists does not work" + ); + const response3 = await send("evm_revert", [snapShotId1]); + assert.strictEqual( + response3, + false, + "Reverting a snapshot that hasn't already been reverted does not work" + ); + const response4 = await send("evm_revert", [999]); + assert.strictEqual( + response4, + false, + "Reverting a snapshot that has never existed does not work" + ); + }); + + it("checkpoints and reverts without persisting contract storage", async () => { + const { accounts, instance, send } = context; + + const snapShotId = await send("evm_snapshot"); + const n1 = await instance.n(); + assert.strictEqual(parseInt(n1), 42, "Initial n is not 42"); + + await instance.inc({ from: accounts[0] }); + const n2 = await instance.n(); + assert.strictEqual( + parseInt(n2), + 43, + "n is not 43 after first call to `inc`" + ); + + await send("evm_revert", [snapShotId]); + const n3 = await instance.n(); + assert.strictEqual( + parseInt(n3), + 42, + "n is not 42 after reverting snapshot" + ); + + // this is the real test. what happened was that the vm's contract storage + // trie cache wasn't cleared when the vm's stateManager cache was cleared. + await instance.inc({ from: accounts[0] }); + const n4 = await instance.n(); + assert.strictEqual( + parseInt(n4), + 43, + "n is not 43 after calling `inc` again" + ); + }); + + it("evm_revert rejects invalid subscriptionId types without crashing", async () => { + const { send } = context; + const ids = [{ foo: "bar" }, true, false, 0.5, Infinity, -Infinity]; + await Promise.all( + ids.map(id => + assert.rejects( + send("evm_revert", [id]), + /Cannot wrap a .+? as a json-rpc type/, + "evm_revert did not reject as expected" + ) + ) + ); + }); + + it("evm_revert rejects null/undefined subscriptionId values", async () => { + const { send } = context; + const ids = [null, undefined]; + await Promise.all( + ids.map(id => + assert.rejects( + send("evm_revert", [id]), + /invalid snapshotId/, + "evm_revert did not reject as expected" + ) + ) + ); + }); + + it("evm_revert returns false for out-of-range subscriptionId values", async () => { + const { send } = context; + const ids = [-1, Buffer.from([0])]; + const promises = ids.map(id => + send("evm_revert", [id]).then(result => + assert.strictEqual(result, false) + ) + ); + await Promise.all(promises); + }); + + it("removes transactions that are already in processing at the start of evm_revert", async () => { + const { + send, + accounts: [from, to] + } = context; + + const snapShotId = await send("evm_snapshot"); + + // increment value for each transaction so the hashes always differ + let value = 1; + + // send some transactions + const inFlightTxs = [ + send("eth_sendTransaction", [{ from, to, value: value++ }]), + send("eth_sendTransaction", [{ from, to, value: value++ }]) + ]; + // wait for the tx hashes to be returned; this is confirmation that + // they've been accepted by the transaction pool. + const txHashes = await Promise.all(inFlightTxs); + + const getReceipt = (hash: string) => + send("eth_getTransactionReceipt", [hash]); + const getTx = (hash: string) => + send("eth_getTransactionByHash", [hash]); + + const receiptsProm = Promise.all(txHashes.map(getReceipt)); + const transactionsProm = Promise.all(txHashes.map(getTx)); + const [receipts, transactions] = await Promise.all([ + receiptsProm, + transactionsProm + ]); + + // sometimes ganache is REALLY fast and mines and saves the first tx + // before we even get here (which is fine). As long as we have tx that + // is still pending (meaning its receipt is `null`) the test is still + // testing what we want it to. + assert.strictEqual( + receipts.some(r => r === null), + true, + "At least 1 receipt should be null" + ); + + // and that the transations were all accepted + transactions.forEach(transaction => { + assert.notStrictEqual( + transaction, + null, + "Transaction should not be null" + ); + }); + + // revert while these transactions are being mined + await send("evm_revert", [snapShotId]); + + const finalReceiptsProm = Promise.all(txHashes.map(getReceipt)); + const finalTransactionsProm = Promise.all(txHashes.map(getTx)); + const [finalReceipts, finalTransactions] = await Promise.all([ + finalReceiptsProm, + finalTransactionsProm + ]); + + // verify that we don't have any receipts + finalReceipts.forEach(receipt => { + assert.strictEqual(receipt, null, "Receipt should be null"); + }); + + // and we don't have any transactions + finalTransactions.forEach(transaction => { + assert.strictEqual(transaction, null, "Transaction should be null"); + }); + }); + + it("removes transactions that are in pending transactions at the start of evm_revert", async () => { + const { + provider, + send, + accounts: [from, to] + } = context; + + const snapShotId = await send("evm_snapshot"); + + // increment value for each transaction so the hashes always differ + let value = 1; + + // send some transactions + const accountNonce = parseInt( + await send("eth_getTransactionCount", [from]), + 16 + ); + const inFlightTxs = [ + send("eth_sendTransaction", [ + { from, to, value: value++, nonce: accountNonce + 1 } + ]), + send("eth_sendTransaction", [ + { from, to, value: value++, nonce: accountNonce + 2 } + ]) + ]; + // wait for the tx hashes to be returned; this is confirmation that + // they've been accepted by the transaction pool. + const txHashes = await Promise.all(inFlightTxs); + + const getReceipt = (hash: string) => + send("eth_getTransactionReceipt", [hash]); + const getTx = (hash: string) => + send("eth_getTransactionByHash", [hash]); + + const transactions = await Promise.all(txHashes.map(getTx)); + + // and that the transations were all accepted + transactions.forEach(transaction => { + assert.notStrictEqual( + transaction, + null, + "Transaction should not be null" + ); + }); + + // revert while these transactions are pending + await send("evm_revert", [snapShotId]); + + // mine a transaction to fill in the nonce gap (this would normally cause the pending transactions to be mined) + await send("eth_sendTransaction", [ + { from, to, value: value++, nonce: accountNonce } + ]); + await provider.once("message"); + + // and mine one more block just to force the any transactions to be immediately mined + await send("evm_mine"); + + const finalReceiptsProm = Promise.all(txHashes.map(getReceipt)); + const finalTransactionsProm = Promise.all(txHashes.map(getTx)); + const [finalReceipts, finalTransactions] = await Promise.all([ + finalReceiptsProm, + finalTransactionsProm + ]); + + // verify that we don't have any receipts + finalReceipts.forEach(receipt => { + assert.strictEqual(receipt, null, "Receipt should be null"); + }); + + // and we don't have any transactions + finalTransactions.forEach(transaction => { + assert.strictEqual(transaction, null, "Transaction should be null"); + }); + }); + + it("doesn't revert transactions that were added *after* the start of evm_revert", async () => { + const { + provider, + send, + accounts: [from, to] + } = context; + const accountNonce = parseInt( + await send("eth_getTransactionCount", [from]), + 16 + ); + const snapShotId = await send("evm_snapshot"); + + // increment value for each transaction so the hashes always differ + let value = 1; + + // send a transaction so we have something to revert + const revertedTx = await send("eth_sendTransaction", [ + { from, to, value: value++ } + ]); + await provider.once("message"); + + // revert while these transactions are being mined + const revertPromise = send("evm_revert", [snapShotId]); + + const txsMinedProm = new Promise(resolve => { + let count = 0; + const unsub = provider.on("message", m => { + if (++count === 2) { + unsub(); + resolve(null); + } + }); + }); + + // send some transactions + const inFlightTxs = [ + send("eth_sendTransaction", [{ from, to, value: value++ }]), + send("eth_sendTransaction", [{ from, to, value: value++ }]) + ]; + + // these two transactions have nonces that are too high to be executed immediately + const laterTxs = [ + send("eth_sendTransaction", [ + { from, to, value: value++, nonce: accountNonce + 3 } + ]), + send("eth_sendTransaction", [ + { from, to, value: value++, nonce: accountNonce + 3 } + ]) + ]; + + // wait for the tx hashes to be returned; this is confirmation that + // they've been accepted by the transaction pool. + const txHashPromises = Promise.all(inFlightTxs); + + const getReceipt = (hash: string) => + send("eth_getTransactionReceipt", [hash]); + const getTx = (hash: string) => + send("eth_getTransactionByHash", [hash]); + + // wait for the revert to finish up + const result = await Promise.race([revertPromise, txHashPromises]); + assert.strictEqual( + result, + true, + "evm_revert should finish before the transaction hashes are returned" + ); + + // wait for the inFlightTxs to be mined + await txsMinedProm; + const txHashes = await txHashPromises; + const laterHashes = await Promise.all(laterTxs); + + // and mine one more block just to force the any executable transactions + // to be immediately mined + + const gotTxsProm = new Promise(resolve => { + let count = 0; + const unsub = provider.on("message", m => { + if (++count === 3) { + unsub(); + resolve(null); + } + }); + }); + + await send("evm_mine"); + + const finalReceiptsProm = Promise.all(txHashes.map(getReceipt)); + const finalTransactionsProm = Promise.all(txHashes.map(getTx)); + const [finalReceipts, finalTransactions] = await Promise.all([ + finalReceiptsProm, + finalTransactionsProm + ]); + + // verify that we do have the receipts + finalReceipts.forEach(receipt => { + assert.notStrictEqual(receipt, null, "Receipt should not be null"); + }); + + // and we do have the transactions + finalTransactions.forEach(transaction => { + assert.notStrictEqual( + transaction, + null, + "Transaction should not be null" + ); + }); + + const laterTxsReceiptsProm = Promise.all(laterHashes.map(getReceipt)); + const laterTxsTransactionsProm = Promise.all(laterHashes.map(getTx)); + const [laterTxsReceipts, laterTxsTransactions] = await Promise.all([ + laterTxsReceiptsProm, + laterTxsTransactionsProm + ]); + + // verify that we do NOT have the receipts + laterTxsReceipts.forEach(receipt => { + assert.strictEqual(receipt, null, "Receipt should be null"); + }); + + // and we DO have the transactions + laterTxsTransactions.forEach(transaction => { + assert.notStrictEqual( + transaction, + null, + "Transaction should not be null" + ); + }); + + // send one more transaction to fill in the gap + send("eth_sendTransaction", [{ from, to, value: value++ }]); + await gotTxsProm; + + const finalLaterTxsReceiptsProm = Promise.all(txHashes.map(getReceipt)); + const finalLaterTxsTransactionsProm = Promise.all(txHashes.map(getTx)); + const [ + finalLaterTxsReceipts, + finalLaterTxsTransactions + ] = await Promise.all([ + finalLaterTxsReceiptsProm, + finalLaterTxsTransactionsProm + ]); + + // verify that we do have the receipts + finalLaterTxsReceipts.forEach(receipt => { + assert.notStrictEqual(receipt, null, "Receipt should not be null"); + }); + + // and we do have the transactions + finalLaterTxsTransactions.forEach(transaction => { + assert.notStrictEqual( + transaction, + null, + "Transaction should not be null" + ); + }); + + const revertedTxReceipt = await getReceipt(revertedTx); + const revertedTxTransactions = await getTx(revertedTx); + assert.strictEqual( + revertedTxReceipt, + null, + "First transaction should not have a receipt" + ); + assert.strictEqual( + revertedTxTransactions, + null, + "First transaction should not have a tx" + ); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/miner/miner.test.ts b/src/chains/ethereum/tests/api/miner/miner.test.ts new file mode 100644 index 0000000000..cc2c05e722 --- /dev/null +++ b/src/chains/ethereum/tests/api/miner/miner.test.ts @@ -0,0 +1,131 @@ +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +import getProvider from "../../helpers/getProvider"; + +describe("api", () => { + describe("miner", () => { + let provider: EthereumProvider; + let accounts: string[]; + + beforeEach(async () => { + provider = await getProvider(); + accounts = await provider.send("eth_accounts"); + }); + + describe("miner_stop/eth_mining/miner_start", () => { + async function testStopStartMining(provider) { + const initialBlockNumber = parseInt( + await provider.send("eth_blockNumber") + ); + const [account] = await provider.send("eth_accounts"); + + // stop the miner + const stopped = await provider.send("miner_stop"); + assert.strictEqual(stopped, true); + + // check that eth_mining returns the correct status + let miningStatus = await provider.send("eth_mining"); + assert.strictEqual(miningStatus, false); + + // send a transaction, and make sure it does *not* get mined + await provider.send("eth_subscribe", ["newHeads"]); + const txHash = await provider.send("eth_sendTransaction", [ + { from: account, to: account, value: 1 } + ]); + const fail = () => + assert.fail( + "No message should have been received while mining was stopped" + ); + provider.on("message", fail); + await new Promise(resolve => setTimeout(resolve, 2000)); + provider.off("message", fail); + + // let's relaly make sure it wasn't mined by checking for a receipt + let receipt = await provider.send("eth_getTransactionReceipt", [ + txHash + ]); + assert.strictEqual(receipt, null); + + // now start the miner back up + const prom = provider.once("message"); + const started = await provider.send("miner_start"); + assert.strictEqual(started, true); + + // check that eth_mining returns the correct status + miningStatus = await provider.send("eth_mining"); + assert.strictEqual(miningStatus, true); + + // wait for the transaction to be mined + await prom; + receipt = await provider.send("eth_getTransactionReceipt", [txHash]); + + // make sure we're on the next block! + assert.strictEqual( + parseInt(receipt.blockNumber), + initialBlockNumber + 1 + ); + } + + it("should stop mining, then mine when started", async () => { + const provider = await getProvider(); + await testStopStartMining(provider); + }).timeout(3000); + + it("should stop mining, then mine when started", async () => { + const provider = await getProvider({ miner: { blockTime: 1 } }); + await testStopStartMining(provider); + }).timeout(4000); + }); + + describe("miner_setEtherbase", () => { + it("sets the etherbase", async () => { + const setState = await provider.send("miner_setEtherbase", [ + accounts[1] + ]); + assert.strictEqual(setState, true); + + const coinbase = await provider.send("eth_coinbase"); + assert.strictEqual(coinbase, accounts[1]); + + await provider.send("eth_subscribe", ["newHeads"]); + const txHash = await provider.send("eth_sendTransaction", [ + { from: accounts[0], to: accounts[0] } + ]); + await provider.once("message"); + const { + status, + blockNumber + } = await provider.send("eth_getTransactionReceipt", [txHash]); + assert.strictEqual(status, "0x1"); + const { miner } = await provider.send("eth_getBlockByNumber", [ + blockNumber + ]); + assert.strictEqual(miner, accounts[1]); + }); + }); + + describe("miner_setGasPrice", () => { + it("sets the gasPrice and uses it as the default price in tranactions", async () => { + const newGasPrice = "0xffff"; + const setState = await provider.send("miner_setGasPrice", [ + newGasPrice + ]); + assert.strictEqual(setState, true); + + const ethGasPrice = await provider.send("eth_gasPrice"); + assert.strictEqual(ethGasPrice, newGasPrice); + + await provider.send("eth_subscribe", ["newHeads"]); + const txHash = await provider.send("eth_sendTransaction", [ + { from: accounts[0], to: accounts[0] } + ]); + await provider.once("message"); + + const { gasPrice } = await provider.send("eth_getTransactionByHash", [ + txHash + ]); + assert.strictEqual(gasPrice, newGasPrice); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/net/net.test.ts b/src/chains/ethereum/tests/api/net/net.test.ts new file mode 100644 index 0000000000..02d6cc4970 --- /dev/null +++ b/src/chains/ethereum/tests/api/net/net.test.ts @@ -0,0 +1,26 @@ +import assert from "assert"; +import getProvider from "../../helpers/getProvider"; + +describe("api", () => { + describe("net", () => { + it("net_version", async () => { + const roundedTo5Seconds = (num: number) => Math.round(num / 5000) * 5000; + const nowIsh = roundedTo5Seconds(Date.now()); + const provider = await getProvider(); + const netVersion = await provider.send("net_version"); + assert.strictEqual(roundedTo5Seconds(netVersion), nowIsh); + }); + + it("net_listening", async () => { + const provider = await getProvider(); + const netListening = await provider.send("net_listening"); + assert.strictEqual(netListening, true); + }); + + it("net_peerCount", async () => { + const provider = await getProvider(); + const peerCount = await provider.send("net_peerCount"); + assert.strictEqual(peerCount, "0x0"); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/personal/personal.test.ts b/src/chains/ethereum/tests/api/personal/personal.test.ts new file mode 100644 index 0000000000..c9a62effc2 --- /dev/null +++ b/src/chains/ethereum/tests/api/personal/personal.test.ts @@ -0,0 +1,341 @@ +import assert from "assert"; +import getProvider from "../../helpers/getProvider"; +import { Quantity } from "@ganache/utils"; +import EthereumProvider from "../../../src/provider"; + +describe("api", () => { + describe("personal", () => { + describe("listAccounts", () => { + it("matches eth_accounts", async () => { + const provider = await getProvider({ wallet: { seed: "temet nosce" } }); + const accounts = await provider.send("eth_accounts"); + const personalAccounts = await provider.send("personal_listAccounts"); + assert.deepStrictEqual(personalAccounts, accounts); + }); + }); + + async function testLockedAccountWithPassphraseViaEth_SendTransaction( + provider: EthereumProvider, + newAccount: string, + passphrase: string + ) { + const transaction = { + from: newAccount, + to: newAccount, + gasLimit: 21000, + gasPrice: 0, + value: 0, + nonce: 0 + }; + + // make sure we can't use the account via eth_sendTransaction + await assert.rejects( + provider.send("eth_sendTransaction", [transaction]), + { + message: "authentication needed: password or unlock" + }, + "eth_sendTransaction should have rejected due to locked from account without its passphrase" + ); + + // unlock the account indefinitely + const unlocked = await provider.send("personal_unlockAccount", [ + newAccount, + passphrase, + 0 + ]); + assert.strictEqual(unlocked, true); + + await provider.send("eth_subscribe", ["newHeads"]); + + // send a normal transaction + const transactionHash = await provider.send("eth_sendTransaction", [ + transaction + ]); + await provider.once("message"); + + // ensure sure it worked + const receipt = await provider.send("eth_getTransactionReceipt", [ + transactionHash + ]); + assert.strictEqual( + receipt.status, + "0x1", + "Transaction failed when it should have succeeded" + ); + + // lock the account + const accountLocked = await provider.send("personal_lockAccount", [ + newAccount + ]); + assert.strictEqual(accountLocked, true); + + // make sure it is locked + await assert.rejects( + provider.send("eth_sendTransaction", [ + Object.assign({}, transaction, { nonce: 1 }) + ]), + { + message: "authentication needed: password or unlock" + }, + "personal_lockAccount didn't work" + ); + } + + async function testLockedAccountWithPassphraseViaPersonal_SendTransaction( + provider: EthereumProvider, + newAccount: string, + passphrase: string + ) { + const transaction = { + from: newAccount, + to: newAccount, + gasLimit: 21000, + gasPrice: 0, + value: 0, + nonce: 0 + }; + + // make sure we can't use the account via personal_sendTransaction and no passphrase + await assert.rejects( + provider.send("personal_sendTransaction", [transaction, undefined]), + { + message: "could not decrypt key with given password" + }, + "personal_sendTransaction should have rejected due to locked from account without its passphrase" + ); + + // make sure we can't use the account with bad passphrases + const invalidPassphrases = [ + "this is not my passphrase", + null, + undefined, + Buffer.allocUnsafe(0), + 1, + 0, + Infinity, + NaN + ]; + await Promise.all( + invalidPassphrases.map(invalidPassphrase => { + return assert.rejects( + provider.send("personal_sendTransaction", [ + transaction, + invalidPassphrase as any + ]), + { + message: "could not decrypt key with given password" + }, + "Transaction should have rejected due to locked from account with wrong passphrase" + ); + }) + ); + + // use personal_sendTransaction with the valid passphrase + await provider.send("eth_subscribe", ["newHeads"]); + const transactionHashPromise = provider.send("personal_sendTransaction", [ + transaction, + passphrase + ]); + const msgPromise = transactionHashPromise.then(() => + provider.once("message") + ); + + await assert.rejects( + provider.send("eth_sendTransaction", [ + Object.assign({}, transaction, { nonce: 1 }) + ]), + { + message: "authentication needed: password or unlock" + }, + "personal_sendTransaction should not unlock the while transaction is bring processed" + ); + + const transactionHash = await transactionHashPromise; + await msgPromise; + + const receipt = await provider.send("eth_getTransactionReceipt", [ + transactionHash + ]); + assert.strictEqual( + receipt.status, + "0x1", + "Transaction failed when it should have succeeded" + ); + + // ensure the account is still locked + await assert.rejects( + provider.send("eth_sendTransaction", [ + Object.assign({}, transaction, { nonce: 1 }) + ]), + { + message: "authentication needed: password or unlock" + }, + "personal_sendTransaction should still be locked the after the transaction is processed" + ); + } + + describe("newAccount", () => { + it("generates deterministic accounts", async () => { + const controlProvider = await getProvider(); + const provider = await getProvider(); + const newAccount = await provider.send("personal_newAccount", [""]); + const controlAccount = await controlProvider.send( + "personal_newAccount", + [""] + ); + assert.strictEqual(newAccount, controlAccount); + }); + + it("generates different accounts based on the `seed` option", async () => { + const controlProvider = await getProvider(); + const provider = await getProvider({ wallet: { seed: "temet nosce" } }); + const newAccount = await provider.send("personal_newAccount", [""]); + const controlAccount = await controlProvider.send( + "personal_newAccount", + [""] + ); + assert.notStrictEqual(newAccount, controlAccount); + }); + + it("generates different accounts based on the `mnemonic` option", async () => { + const controlProvider = await getProvider(); + const provider = await getProvider({ + wallet: { mnemonic: "sweet treat" } + }); + const newAccount = await provider.send("personal_newAccount", [""]); + const controlAccount = await controlProvider.send( + "personal_newAccount", + [""] + ); + assert.notStrictEqual(newAccount, controlAccount); + }); + + it("generates different accounts on successive calls", async () => { + const provider = await getProvider(); + const firstNewAccount = await provider.send("personal_newAccount", [ + "" + ]); + const secondNewAccount = await provider.send("personal_newAccount", [ + "" + ]); + assert.notStrictEqual(firstNewAccount, secondNewAccount); + }); + + it("generates different accounts on successive calls based on the seed", async () => { + const controlProvider = await getProvider(); + const provider = await getProvider({ wallet: { seed: "temet nosce" } }); + const firstNewAccount = await provider.send("personal_newAccount", [ + "" + ]); + const secondNewAccount = await provider.send("personal_newAccount", [ + "" + ]); + + await provider.send("personal_newAccount", [""]); + const controlSecondNewAccount = await controlProvider.send( + "personal_newAccount", + [""] + ); + + assert.notStrictEqual( + firstNewAccount, + secondNewAccount, + "First and second generated accounts are the same when they shouldn't be" + ); + assert.notStrictEqual( + secondNewAccount, + controlSecondNewAccount, + "Second account is identical to control's second account when it shouldn't be" + ); + }); + + describe("personal_unlockAccount ➡ eth_sendTransaction ➡ personal_lockAccount", () => { + it("generates locked accounts with passphrase", async () => { + const provider = await getProvider({ miner: { gasPrice: 0 } }); + const passphrase = "this is my passphrase"; + // generate an account + const newAccount = await provider.send("personal_newAccount", [ + passphrase + ]); + + testLockedAccountWithPassphraseViaEth_SendTransaction( + provider, + newAccount, + passphrase + ); + }); + }); + + describe("personal_sendTransaction", () => { + it("generates locked accounts with passphrase", async () => { + const provider = await getProvider({ miner: { gasPrice: 0 } }); + const passphrase = "this is my passphrase"; + // generate an account + const newAccount = await provider.send("personal_newAccount", [ + passphrase + ]); + + testLockedAccountWithPassphraseViaPersonal_SendTransaction( + provider, + newAccount, + passphrase + ); + }); + }); + }); + + describe("personal_importRawKey", () => { + const secretKey = + "0x0123456789012345678901234567890123456789012345678901234567890123"; + const passphrase = "this is my passphrase"; + + it("should return the known account address", async () => { + const provider = await getProvider(); + const newAccount = await provider.send("personal_importRawKey", [ + secretKey, + passphrase + ]); + assert.strictEqual( + newAccount, + "0x14791697260e4c9a71f18484c9f997b308e59325", + "Raw account not imported correctly" + ); + }); + + describe("personal_unlockAccount ➡ eth_sendTransaction ➡ personal_lockAccount", () => { + it("generates locked accounts with passphrase", async () => { + const provider = await getProvider({ miner: { gasPrice: 0 } }); + const passphrase = "this is my passphrase"; + // generate an account + const newAccount = await provider.send("personal_importRawKey", [ + secretKey, + passphrase + ]); + + await testLockedAccountWithPassphraseViaEth_SendTransaction( + provider, + newAccount, + passphrase + ); + }); + }); + + describe("personal_sendTransaction", () => { + it("generates locked accounts with passphrase", async () => { + const provider = await getProvider({ miner: { gasPrice: 0 } }); + // generate an account + const newAccount = await provider.send("personal_importRawKey", [ + secretKey, + passphrase + ]); + + await testLockedAccountWithPassphraseViaPersonal_SendTransaction( + provider, + newAccount, + passphrase + ); + }); + }); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/rpc/modules.test.ts b/src/chains/ethereum/tests/api/rpc/modules.test.ts new file mode 100644 index 0000000000..d4fe8f4c1b --- /dev/null +++ b/src/chains/ethereum/tests/api/rpc/modules.test.ts @@ -0,0 +1,25 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +const RPC_MODULES = { + eth: "1.0", + net: "1.0", + rpc: "1.0", + web3: "1.0", + evm: "1.0", + personal: "1.0" +} as const; + +describe("api", () => { + describe("rpc", () => { + let provider: EthereumProvider; + before(async () => { + provider = await getProvider(); + }); + + it("rpc_modules returns the modules", async () => { + const result = await provider.send("rpc_modules"); + assert.deepStrictEqual(result, RPC_MODULES); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/shh/shh.test.ts b/src/chains/ethereum/tests/api/shh/shh.test.ts new file mode 100644 index 0000000000..51e8053178 --- /dev/null +++ b/src/chains/ethereum/tests/api/shh/shh.test.ts @@ -0,0 +1,62 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; + +describe("api", () => { + describe("shh", () => { + let provider: EthereumProvider; + before(async () => { + provider = await getProvider(); + }); + + it("returns it's shh_newIdentity status", async () => { + const result = await provider.send("shh_newIdentity"); + assert.deepStrictEqual(result, "0x00"); + }); + + it("returns it's shh_hasIdentity status", async () => { + const result = await provider.send("shh_hasIdentity", ["0x0"]); + assert.strictEqual(result, false); + }); + + it("returns false for shh_addToGroup", async () => { + const result = await provider.send("shh_addToGroup", ["0x0"]); + assert.strictEqual(result, false); + }); + + it("returns it's shh_newGroup status", async () => { + const result = await provider.send("shh_newGroup"); + assert.deepStrictEqual(result, "0x00"); + }); + + it("returns false for shh_newFilter", async () => { + const result = await provider.send("shh_newFilter", ["0x0", []]); + assert.strictEqual(result, false); + }); + + it("returns false for shh_uninstallFilter", async () => { + const result = await provider.send("shh_uninstallFilter", ["0x0"]); + assert.strictEqual(result, false); + }); + + it("returns []] for shh_getFilterChanges", async () => { + const result = await provider.send("shh_getFilterChanges", ["0x0"]); + assert.deepStrictEqual(result, []); + }); + + it("returns false for shh_getMessages", async () => { + const result = await provider.send("shh_getMessages", ["0x0"]); + assert.strictEqual(result, false); + }); + + it("returns false for shh_post", async () => { + const result = await provider.send("shh_post", [{}]); + assert.strictEqual(result, false); + }); + + it("returns 2 for shh_version", async () => { + const result = await provider.send("shh_version"); + assert.strictEqual(result, "2"); + }); + }); +}); diff --git a/src/chains/ethereum/tests/api/web3/web3.test.ts b/src/chains/ethereum/tests/api/web3/web3.test.ts new file mode 100644 index 0000000000..a87f8949dd --- /dev/null +++ b/src/chains/ethereum/tests/api/web3/web3.test.ts @@ -0,0 +1,31 @@ +import getProvider from "../../helpers/getProvider"; +import assert from "assert"; +import EthereumProvider from "../../../src/provider"; +const { version } = require("../../../../../packages/ganache/package.json"); + +describe("api", () => { + describe("web3", () => { + let provider: EthereumProvider; + before(async () => { + provider = await getProvider(); + }); + + it("web3_clientVersion returns the client version", async () => { + const result = await provider.send("web3_clientVersion"); + assert.deepStrictEqual( + result, + `Ganache/v${version}/EthereumJS TestRPC/v${version}/ethereum-js` + ); + }); + + it("web3_sha should hash the given input", async () => { + const input = "Tim is a swell guy."; + const result = await provider.send("web3_sha3", [input]); + + assert.strictEqual( + result, + "0xee80d4ac03202e2246d51a596c76a18e1a6d899bed9f05246d998fb656d9bd1f" + ); + }); + }); +}); diff --git a/src/chains/ethereum/tests/contracts/HelloWorld.sol b/src/chains/ethereum/tests/contracts/HelloWorld.sol new file mode 100644 index 0000000000..59e7b6f1d5 --- /dev/null +++ b/src/chains/ethereum/tests/contracts/HelloWorld.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.4; + +contract HelloWorld { + uint256 public value; + + event ValueSet(uint256); + + constructor() payable { + value = 5; + } + + function setValue(uint256 val) public { + value = val; + emit ValueSet(val); + } + + function getConstVal() public pure returns (uint8) { + return 123; + } +} diff --git a/src/chains/ethereum/tests/helpers/compile.ts b/src/chains/ethereum/tests/helpers/compile.ts new file mode 100644 index 0000000000..4b64cbbe21 --- /dev/null +++ b/src/chains/ethereum/tests/helpers/compile.ts @@ -0,0 +1,51 @@ +import solc from "solc"; + +{ + // Clean up after solc. Looks like this never really got fixed: + // https://github.com/chriseth/browser-solidity/issues/167 + const listeners = process.listeners("unhandledRejection"); + const solcListener = listeners[listeners.length - 1]; + if (solcListener && solcListener.name === "abort") { + process.removeListener("unhandledRejection", solcListener); + } else { + throw new Error( + "Looks like either the solc listener was finally removed, or they changed the name. Check it!" + ); + } +} + +import { readFileSync } from "fs-extra"; +import { parse } from "path"; + +export default function compile(contractPath: string, contractName?: string) { + const parsedPath = parse(contractPath); + const content = readFileSync(contractPath, { encoding: "utf8" }); + const globalName = parsedPath.base; + contractName ||= parsedPath.name; + + let result = JSON.parse( + solc.compile( + JSON.stringify({ + language: "Solidity", + sources: { + [globalName]: { + content + } + }, + settings: { + outputSelection: { + "*": { + "*": ["*"] + } + } + } + } as solc.CompilerInput) + ) + ) as solc.CompilerOutput; + + const contract = result.contracts[globalName][contractName]; + return { + code: "0x" + contract.evm.bytecode.object, + contract + }; +} diff --git a/src/chains/ethereum/tests/helpers/getProvider.ts b/src/chains/ethereum/tests/helpers/getProvider.ts new file mode 100644 index 0000000000..1814c4f8a3 --- /dev/null +++ b/src/chains/ethereum/tests/helpers/getProvider.ts @@ -0,0 +1,41 @@ +import { utils } from "@ganache/utils"; +import EthereumProvider from "../../src/provider"; +import { EthereumProviderOptions } from "../../src/options"; +const { RequestCoordinator, Executor } = utils; + +const mnemonic = + "into trim cross then helmet popular suit hammer cart shrug oval student"; + +type Writeable = { -readonly [P in keyof T]: T[P] }; + +const getProvider = async ( + options: Writeable = { + wallet: { mnemonic: mnemonic } + } +) => { + options.chain = options.chain || {}; + options.logging = options.logging || { logger: { log: () => {} } }; + + // set `asyncRequestProcessing` to `true` by default + let doAsync = options.chain.asyncRequestProcessing; + doAsync = options.chain.asyncRequestProcessing = + doAsync != null ? doAsync : true; + + // don't write to stdout in tests + if (!options.logging.logger) { + options.logging.logger = { log: () => {} }; + } + + const requestCoordinator = new RequestCoordinator(doAsync ? 0 : 1); + const executor = new Executor(requestCoordinator); + const provider = new EthereumProvider(options, executor); + await new Promise(resolve => { + provider.on("connect", () => { + requestCoordinator.resume(); + resolve(void 0); + }); + }); + return provider; +}; + +export default getProvider; diff --git a/src/chains/ethereum/tests/provider.test.ts b/src/chains/ethereum/tests/provider.test.ts new file mode 100644 index 0000000000..14aaab9fe3 --- /dev/null +++ b/src/chains/ethereum/tests/provider.test.ts @@ -0,0 +1,55 @@ +import assert from "assert"; +import EthereumProvider from "../src/provider"; +import getProvider from "./helpers/getProvider"; +import { JsonRpcTypes } from "@ganache/utils"; +import EthereumApi from "../src/api"; + +describe("provider", () => { + describe("options", () => { + it("generates predictable accounts when given a seed", async () => { + const provider = await getProvider({ wallet: { seed: "temet nosce" } }); + const accounts = await provider.send("eth_accounts"); + assert.strictEqual( + accounts[0], + "0x59ef313e6ee26bab6bcb1b5694e59613debd88da" + ); + }); + }); + + describe("interface", () => { + const networkId = 1234; + let provider: EthereumProvider; + + beforeEach(async () => { + provider = await getProvider({ chain: { networkId } }); + }); + + it("returns things via EIP-1193", async () => { + assert.strictEqual(await provider.send("net_version"), `${networkId}`); + }); + + it("returns things via legacy", async () => { + const jsonRpcRequest: JsonRpcTypes.Request = { + id: "1", + jsonrpc: "2.0", + method: "net_version" + }; + const methods = ["send", "sendAsync"] as const; + return Promise.all( + methods + .map(method => { + return new Promise((resolve, reject) => { + provider[method](jsonRpcRequest, (err: Error, { result }) => { + if (err) return reject(err); + assert.strictEqual(result, `${networkId}`); + resolve(void 0); + }); + }); + }) + .map(async prom => { + assert.strictEqual(await prom, void 0); + }) + ); + }); + }); +}); diff --git a/src/chains/ethereum/tests/temp-tests.test.ts b/src/chains/ethereum/tests/temp-tests.test.ts new file mode 100644 index 0000000000..e5f17da2aa --- /dev/null +++ b/src/chains/ethereum/tests/temp-tests.test.ts @@ -0,0 +1,315 @@ +import os from "os"; +import fs from "fs"; +import assert from "assert"; +import getProvider from "./helpers/getProvider"; +import compile from "./helpers/compile"; +import { join } from "path"; + +/** + * test in here are playground tests or just tests that are in the original + * ganache-core but have yet been properly ported over yet. + */ + +describe("Random tests that are temporary!", () => { + const expectedAddress = "0x604a95c9165bc95ae016a5299dd7d400dddbea9a"; + const mnemonic = + "into trim cross then helmet popular suit hammer cart shrug oval student"; + + it("should respect the BIP99 mnemonic", async () => { + const options = { wallet: { mnemonic } }; + const p = await getProvider(options); + const accounts = await p.send("eth_accounts"); + + assert.strictEqual(accounts[0], expectedAddress); + }); + + it("eth_sendTransaction", async () => { + const options = { wallet: { mnemonic } }; + const p = await getProvider(options); + const accounts = await p.send("eth_accounts"); + const balance1_1 = await p.send("eth_getBalance", [accounts[1]]); + await p.send("eth_subscribe", ["newHeads"]); + await p.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 1 + } + ]); + await p.once("message"); + + const balance1_2 = await p.send("eth_getBalance", [accounts[1]]); + assert.strictEqual(parseInt(balance1_1) + 1, parseInt(balance1_2)); + }); + + it("should create its own mnemonic", async () => { + const p = await getProvider(); + const options = p.getOptions(); + assert.deepStrictEqual(typeof options.wallet.mnemonic, "string"); + }); + + it("shouldn't allow initialization without accounts", async () => { + const options = { wallet: { totalAccounts: 0 } } as any; + await assert.rejects(getProvider(options), { + message: + "Cannot initialize chain: either options.accounts or options.total_accounts must be specified" + }); + + options.wallet.accounts = []; + await assert.rejects(getProvider(options), { + message: + "Cannot initialize chain: either options.accounts or options.total_accounts must be specified" + }); + }); + + it("sets up accounts", async () => { + const privateKey = Buffer.from( + "4646464646464646464646464646464646464646464646464646464646464646", + "hex" + ); + const p = await getProvider({ + wallet: { + accounts: [ + { balance: "0x123", secretKey: "0x" + privateKey.toString("hex") }, + { balance: "0x456" } + ] + } + }); + const accounts = await p.send("eth_accounts"); + assert.strictEqual(accounts.length, 2); + }); + + it("sets errors when unlocked_accounts index is too high", async () => { + await assert.rejects(getProvider({ wallet: { unlockedAccounts: [99] } }), { + message: "Account at index 99 not found. Max index available is 9." + }); + }); + + it("sets errors when unlocked_accounts index is a (big) bigint", async () => { + const bigNumber = BigInt(Number.MAX_SAFE_INTEGER) + 1n; + await assert.rejects( + getProvider({ + wallet: { + unlockedAccounts: [bigNumber.toString()] + } + }), + { + message: `Invalid value in unlocked_accounts: ${bigNumber}` + } + ); + }); + + it("unlocks accounts via unlock_accounts (both string and numbered numbers)", async () => { + const p = await getProvider({ + wallet: { + mnemonic, + secure: true, + unlockedAccounts: ["0", 1] + } + }); + + const accounts = await p.send("eth_accounts"); + const balance1_1 = await p.send("eth_getBalance", [accounts[1]]); + const badSend = async () => { + return p.send("eth_sendTransaction", [ + { + from: accounts[2], + to: accounts[1], + value: 123 + } + ]); + }; + await assert.rejects( + badSend, + "Error: authentication needed: password or unlock" + ); + + await p.send("eth_subscribe", ["newHeads"]); + await p.send("eth_sendTransaction", [ + { + from: accounts[0], + to: accounts[1], + value: 123 + } + ]); + + await p.once("message"); + + const balance1_2 = await p.send("eth_getBalance", [accounts[1]]); + assert.strictEqual(BigInt(balance1_1) + 123n, BigInt(balance1_2)); + + const balance0_1 = await p.send("eth_getBalance", [accounts[0]]); + + await p.send("eth_sendTransaction", [ + { + from: accounts[1], + to: accounts[0], + value: 123 + } + ]); + + await p.once("message"); + + const balance0_2 = await p.send("eth_getBalance", [accounts[0]]); + assert.strictEqual(BigInt(balance0_1) + 123n, BigInt(balance0_2)); + }); + + it("deploys contracts", async () => { + const contract = compile(join(__dirname, "./contracts/HelloWorld.sol")); + + const p = await getProvider({ + miner: { defaultTransactionGasLimit: 6721975 } + }); + const accounts = await p.send("eth_accounts"); + const from = accounts[3]; + + await p.send("eth_subscribe", ["newHeads"]); + + const transactionHash = await p.send("eth_sendTransaction", [ + { + from, + data: contract.code + } + ]); + + await p.once("message"); + + const receipt = await p.send("eth_getTransactionReceipt", [ + transactionHash + ]); + assert.strictEqual(receipt.blockNumber, "0x1"); + + const to = receipt.contractAddress; + const methods = contract.contract.evm.methodIdentifiers; + + const value = await p.send("eth_call", [ + { from, to, data: "0x" + methods["value()"] } + ]); + + const x5 = + "0x0000000000000000000000000000000000000000000000000000000000000005"; + assert.strictEqual(value, x5); + + const constVal = await p.send("eth_call", [ + { from, to, data: "0x" + methods["getConstVal()"] } + ]); + + const x123 = + "0x000000000000000000000000000000000000000000000000000000000000007b"; + assert.strictEqual(constVal, x123); + + const storage = await p.send("eth_getStorageAt", [ + receipt.contractAddress, + 0, + receipt.blockNumber + ]); + assert.strictEqual(storage, "0x05"); + + const raw25 = + "0000000000000000000000000000000000000000000000000000000000000019"; + const x25 = "0x" + raw25; + const hash = await p.send("eth_sendTransaction", [ + { from, to, data: "0x" + methods["setValue(uint256)"] + raw25 } + ]); + await p.once("message"); + const txReceipt = await p.send("eth_getTransactionReceipt", [hash]); + assert.strictEqual(txReceipt.blockNumber, "0x2"); + + const getValueAgain = await p.send("eth_call", [ + { from, to, data: "0x" + methods["value()"] } + ]); + + assert.strictEqual(getValueAgain, x25); + + const storage2 = await p.send("eth_getStorageAt", [ + receipt.contractAddress, + 0, + txReceipt.blockNumber + ]); + assert.strictEqual(storage2, "0x19"); + }); + + it("transfers value", async () => { + const p = await getProvider({ miner: { gasPrice: 0 } }); + const accounts = await p.send("eth_accounts"); + const ONE_ETHER = 1000000000000000000n; + const startingBalance = 100n * ONE_ETHER; + await p.send("eth_subscribe", ["newHeads"]); + await p.send("eth_sendTransaction", [ + { + from: accounts[1], + to: accounts[2], + value: ONE_ETHER + } + ]); + await p.once("message"); + + const balances = ( + await Promise.all([ + p.send("eth_getBalance", [accounts[1]]), + p.send("eth_getBalance", [accounts[2]]) + ]) + ).map(BigInt); + assert.strictEqual(balances[0], startingBalance - ONE_ETHER); + assert.strictEqual(balances[1], startingBalance + ONE_ETHER); + }); + + it("runs eth_call", async () => { + const privateKey = Buffer.from( + "4646464646464646464646464646464646464646464646464646464646464646", + "hex" + ); + const p = await getProvider({ + wallet: { + accounts: [ + { balance: "0x123", secretKey: "0x" + privateKey.toString("hex") }, + { balance: "0x456" } + ] + } + }); + const accounts = await p.send("eth_accounts"); + const result = await p.send("eth_call", [ + { from: accounts[0], to: accounts[0], value: "0x1" } + ]); + assert(result, "0x"); + }); + + describe("options:account_keys_path", () => { + const fileName = join(os.tmpdir(), "/ganache-core-test-accounts.json"); + + function cleanUp() { + try { + fs.unlinkSync(fileName); + } catch (e) { + // ignore error + } + } + afterEach("clean up", () => { + cleanUp(); + }); + it("should create the file by name", async () => { + await getProvider({ wallet: { accountKeysPath: fileName } }); + assert.strictEqual( + fs.existsSync(fileName), + true, + "The account_keys file doesn't exist." + ); + }); + it("should populate the file by descriptor", async () => { + const fd = fs.openSync(fileName, "w"); + try { + await getProvider({ wallet: { accountKeysPath: fd } }); + assert.strictEqual( + fs.existsSync(fileName), + true, + "The account_keys file doesn't exist." + ); + } finally { + fs.closeSync(fd); + } + }); + afterEach("clean up", () => { + cleanUp(); + }); + }); +}); diff --git a/src/chains/ethereum/tests/tsconfig.json b/src/chains/ethereum/tests/tsconfig.json new file mode 100644 index 0000000000..7f41c2548d --- /dev/null +++ b/src/chains/ethereum/tests/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.json", + "include": ["./"] +} diff --git a/src/chains/ethereum/tsconfig.json b/src/chains/ethereum/tsconfig.json new file mode 100644 index 0000000000..0c41d652c6 --- /dev/null +++ b/src/chains/ethereum/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts"], + "typeRoots": ["./node_modules/@types", "./src/@types"] +} diff --git a/src/chains/ethereum/typedoc.json b/src/chains/ethereum/typedoc.json new file mode 100644 index 0000000000..2b106fd177 --- /dev/null +++ b/src/chains/ethereum/typedoc.json @@ -0,0 +1,13 @@ +{ + "name": "@ganache/ethereum", + "mode": "modules", + "module": "commonjs", + "theme": "../../../node_modules/@trufflesuite/typedoc-default-themes/bin/default/", + "includeDeclarations": false, + "ignoreCompilerErrors": true, + "preserveConstEnums": true, + "excludeExternals": true, + "categoryOrder": [], + "exclude": ["**/test/*"], + "target": "ES6" +} diff --git a/src/chains/tezos/.npmignore b/src/chains/tezos/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/chains/tezos/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/chains/tezos/LICENSE b/src/chains/tezos/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/chains/tezos/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/chains/tezos/README.md b/src/chains/tezos/README.md new file mode 100644 index 0000000000..59fe51bb8c --- /dev/null +++ b/src/chains/tezos/README.md @@ -0,0 +1,3 @@ +# `@ganache/tezos` + +This is ganache's Tezos client implementation. diff --git a/src/chains/tezos/index.ts b/src/chains/tezos/index.ts new file mode 100644 index 0000000000..5a788f80bd --- /dev/null +++ b/src/chains/tezos/index.ts @@ -0,0 +1,42 @@ +import Emittery from "emittery"; +import { utils, types } from "@ganache/utils"; +import Provider from "./src/provider"; +import TezosApi from "./src/api"; +import { HttpRequest } from "uWebSockets.js"; + +export type TezosProvider = Provider; +export const TezosProvider = Provider; + +export class TezosConnector + extends Emittery.Typed + implements types.Connector { + provider: Provider; + #api: TezosApi; + + constructor(providerOptions: any, requestCoordinator: utils.Executor) { + super(); + + const api = (this.#api = new TezosApi()); + this.provider = new Provider(providerOptions); + } + + format(result: any) { + return JSON.stringify(result); + } + + formatError(error: any) { + return JSON.stringify(error); + } + + parse(message: Buffer) { + return JSON.parse(message); + } + + handle(payload: any, _connection: HttpRequest): Promise { + return Promise.resolve(123); + } + + close() { + return {}; + } +} diff --git a/src/chains/tezos/npm-shrinkwrap.json b/src/chains/tezos/npm-shrinkwrap.json new file mode 100644 index 0000000000..8228513ad0 --- /dev/null +++ b/src/chains/tezos/npm-shrinkwrap.json @@ -0,0 +1,1931 @@ +{ + "name": "@ganache/tezos", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@koa/cors": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@koa/cors/-/cors-3.1.0.tgz", + "integrity": "sha512-7ulRC1da/rBa6kj6P4g2aJfnET3z8Uf3SWu60cjbtxTA5g8lxRdX/Bd2P92EagGwwAhANeNw8T8if99rJliR6Q==", + "dev": true, + "requires": { + "vary": "^1.1.2" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@trufflesuite/typedoc-default-themes": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@trufflesuite/typedoc-default-themes/-/typedoc-default-themes-0.6.1.tgz", + "integrity": "sha512-/wt3Jp+fD/DsxArEMixt94hDjHlB6R82Xa2ffjoCzlXrF8OSidzmzYkMvuxi53t1PaQvobNY5wMTXUqGnt/HXA==", + "dev": true, + "requires": { + "backbone": "^1.4.0", + "jquery": "^3.4.1", + "lunr": "^2.3.6", + "underscore": "^1.9.1" + } + }, + "@types/node": { + "version": "14.0.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", + "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "agent-base": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "ansi-escape-sequences": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-5.1.2.tgz", + "integrity": "sha512-JcpoVp1W1bl1Qn4cVuiXEhD6+dyXKSOgCn2zlzE8inYgCJCBy1aPnUhlz6I4DFum8D4ovb9Qi/iAjUcGvG2lqw==", + "dev": true, + "requires": { + "array-back": "^4.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, + "array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", + "dev": true + }, + "backbone": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz", + "integrity": "sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ==", + "dev": true, + "requires": { + "underscore": ">=1.8.3" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "byte-size": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-6.2.0.tgz", + "integrity": "sha512-6EspYUCAPMc7E2rltBgKwhG+Cmk0pDm9zDtF1Awe2dczNUL3YpZ8mTs/dueOTS1hqGWBOatqef4jYMGjln7WmA==", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "dev": true, + "requires": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "co-body": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.0.0.tgz", + "integrity": "sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw==", + "dev": true, + "requires": { + "inflation": "^2.0.0", + "qs": "^6.5.2", + "raw-body": "^2.3.3", + "type-is": "^1.6.16" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "dev": true, + "requires": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true + } + } + }, + "command-line-usage": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", + "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "chalk": "^2.4.2", + "table-layout": "^1.0.0", + "typical": "^5.2.0" + }, + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "common-log-format": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/common-log-format/-/common-log-format-1.0.0.tgz", + "integrity": "sha512-fFn/WPNbsTCGTTwdCpZfVZSa5mgqMEkA0gMTRApFSlEsYN+9B2FPfiqch5FT+jsv5IV1RHV3GeZvCa7Qg+jssw==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "dev": true, + "requires": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + } + } + }, + "copy-to": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", + "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-mixin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/create-mixin/-/create-mixin-3.0.0.tgz", + "integrity": "sha512-LkdMqnWT9LaqBN4huqpUnMz56Yr1mVSoCduAd2xXefgH/YZP2sXCMAyztXjk4q8hTF/TlcDa+zQW2aTgGdjjKQ==", + "dev": true + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "emittery": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", + "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + } + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "highlight.js": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.1.2.tgz", + "integrity": "sha512-Q39v/Mn5mfBlMff9r+zzA+gWxRsCRKwEMvYTiisLr/XUiFI/4puWt0Ojdko3R3JCNWGdOWaA5g/Yxqa23kC5AA==", + "dev": true + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "http-assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", + "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "http-errors": "~1.7.2" + }, + "dependencies": { + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + } + } + }, + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + } + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflation": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", + "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", + "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "dev": true + }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jquery": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", + "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dev": true, + "requires": { + "tsscmp": "1.0.6" + } + }, + "koa": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.0.tgz", + "integrity": "sha512-i/XJVOfPw7npbMv67+bOeXr3gPqOAw6uh5wFyNs3QvJ47tUx3M3V9rIE0//WytY42MKz4l/MXKyGkQ2LQTfLUQ==", + "dev": true, + "requires": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "~3.1.0", + "delegates": "^1.0.0", + "depd": "^1.1.2", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^1.2.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + } + }, + "koa-bodyparser": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", + "integrity": "sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==", + "dev": true, + "requires": { + "co-body": "^6.0.0", + "copy-to": "^2.0.1" + } + }, + "koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "dev": true + }, + "koa-compress": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/koa-compress/-/koa-compress-3.1.0.tgz", + "integrity": "sha512-0m24/yS/GbhWI+g9FqtvStY+yJwTObwoxOvPok6itVjRen7PBWkjsJ8pre76m+99YybXLKhOJ62mJ268qyBFMQ==", + "dev": true, + "requires": { + "bytes": "^3.0.0", + "compressible": "^2.0.0", + "koa-is-json": "^1.0.0", + "statuses": "^1.0.0" + } + }, + "koa-conditional-get": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/koa-conditional-get/-/koa-conditional-get-2.0.0.tgz", + "integrity": "sha1-pD83I8HQFLcwo07Oit8wuTyCM/I=", + "dev": true + }, + "koa-convert": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", + "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", + "dev": true, + "requires": { + "co": "^4.6.0", + "koa-compose": "^3.0.0" + }, + "dependencies": { + "koa-compose": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", + "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", + "dev": true, + "requires": { + "any-promise": "^1.1.0" + } + } + } + }, + "koa-etag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/koa-etag/-/koa-etag-3.0.0.tgz", + "integrity": "sha1-nvc4Ld1agqsN6xU0FckVg293HT8=", + "dev": true, + "requires": { + "etag": "^1.3.0", + "mz": "^2.1.0" + } + }, + "koa-is-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", + "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=", + "dev": true + }, + "koa-json": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/koa-json/-/koa-json-2.0.2.tgz", + "integrity": "sha1-Nq8U5uofXWRtfESihXAcb4Wk/eQ=", + "dev": true, + "requires": { + "koa-is-json": "1", + "streaming-json-stringify": "3" + } + }, + "koa-morgan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/koa-morgan/-/koa-morgan-1.0.1.tgz", + "integrity": "sha1-CAUuDODYOdPEMXi5CluzQkvvH5k=", + "dev": true, + "requires": { + "morgan": "^1.6.1" + } + }, + "koa-range": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/koa-range/-/koa-range-0.3.0.tgz", + "integrity": "sha1-NYjjSWRzqDmhvSZNKkKx2FvX/qw=", + "dev": true, + "requires": { + "stream-slice": "^0.1.2" + } + }, + "koa-route": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/koa-route/-/koa-route-3.2.0.tgz", + "integrity": "sha1-dimLmaa8+p44yrb+XHmocz51i84=", + "dev": true, + "requires": { + "debug": "*", + "methods": "~1.1.0", + "path-to-regexp": "^1.2.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "koa-send": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", + "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "koa-static": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", + "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + } + }, + "load-module": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/load-module/-/load-module-3.0.0.tgz", + "integrity": "sha512-ZqprfrTx4vfH5+1mgpspPh5JYsNyA193NkMUdb3GwpmVqMczOh8cUDJgZBmEZVlSR42JBGYTUxlBAX9LHIBtIA==", + "dev": true, + "requires": { + "array-back": "^4.0.1" + } + }, + "local-web-server": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/local-web-server/-/local-web-server-4.2.1.tgz", + "integrity": "sha512-v71LZool2w7uYA+tDP5HhfjzUxz5SFfcrPPB/zC98yFFawt7A6fcmAr2MR4Q9AHk/A8oyd/wrhEJBJLndwHxNQ==", + "dev": true, + "requires": { + "lws": "^3.1.0", + "lws-basic-auth": "^2.0.0", + "lws-blacklist": "^3.0.0", + "lws-body-parser": "^2.0.0", + "lws-compress": "^2.0.0", + "lws-conditional-get": "^2.0.0", + "lws-cors": "^3.0.0", + "lws-index": "^2.0.0", + "lws-json": "^2.0.0", + "lws-log": "^2.0.0", + "lws-mime": "^2.0.0", + "lws-range": "^3.0.0", + "lws-request-monitor": "^2.0.0", + "lws-rewrite": "^3.1.1", + "lws-spa": "^3.0.0", + "lws-static": "^2.0.0", + "node-version-matches": "^2.0.1" + } + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, + "lodash.assignwith": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", + "integrity": "sha1-EnqX8CrcQXUalU0ksN4X4QDgOOs=", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", + "dev": true + }, + "lunr": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", + "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==", + "dev": true + }, + "lws": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lws/-/lws-3.1.0.tgz", + "integrity": "sha512-I8rTgZxz8OJL0hjdlDxs6WpcVG7WSyalVHPQXXK+WPNVjm3KhkT5gV0Qmsgm2FRLbRUp15tso80xmDxMsyt7zA==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^5.1.2", + "array-back": "^4.0.1", + "byte-size": "^6.2.0", + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "create-mixin": "^3.0.0", + "koa": "^2.11.0", + "load-module": "^3.0.0", + "lodash.assignwith": "^4.2.0", + "node-version-matches": "^2.0.1", + "open": "^7.0.4", + "qrcode-terminal": "^0.12.0", + "reduce-flatten": "^3.0.0", + "typical": "^6.0.0", + "walk-back": "^4.0.0" + } + }, + "lws-basic-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-basic-auth/-/lws-basic-auth-2.0.0.tgz", + "integrity": "sha512-zzyoGFLQPuKaQJvHMLmmSyfT6lIvocwcDXllTVW5brD0t0YgHYopILkzja+x+MIlJX/YhNKniaTSasujniYVjw==", + "dev": true, + "requires": { + "basic-auth": "^2.0.1" + } + }, + "lws-blacklist": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lws-blacklist/-/lws-blacklist-3.0.0.tgz", + "integrity": "sha512-KNXGDBmbj+UGfWMBAefe2vrfuWpEQms/9Fd7kfMScTqAKF6nrVoEs4pkxfefArG3bX0bu7jWLyB4tJGma5WC6Q==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "path-to-regexp": "^6.1.0" + } + }, + "lws-body-parser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-body-parser/-/lws-body-parser-2.0.0.tgz", + "integrity": "sha512-QFDzln3sSdKWL9fVNWy2+ZmrKy/XaYRO0/FFB0MBrDCsNnzepeCD4I7rOOfyuphLn42yR8XUpWdcJ3Ii5aauRA==", + "dev": true, + "requires": { + "koa-bodyparser": "^4.2.1" + } + }, + "lws-compress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-compress/-/lws-compress-2.0.0.tgz", + "integrity": "sha512-5qDXI9pukVYWm07WjAOfpItLXKtL8lCHvjmW4RiXULhTRJj1qqBjNcmqReyk8L7NLUKhc+8eqoDDJFKURQEp0w==", + "dev": true, + "requires": { + "koa-compress": "^3.0.0" + } + }, + "lws-conditional-get": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-conditional-get/-/lws-conditional-get-2.0.0.tgz", + "integrity": "sha512-U05yDlFJKIYa7gJZYfnc1HIEuXbKpDJztgkvNYyxCqJC28j/k9ORoNnFNOIHpBh/jlPJgV8x7uH34mIxFAryWA==", + "dev": true, + "requires": { + "koa-conditional-get": "^2.0.0", + "koa-etag": "^3.0.0" + } + }, + "lws-cors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lws-cors/-/lws-cors-3.0.0.tgz", + "integrity": "sha512-diUkoyVZyzLB8LamdtUYYAfJdPAyu/+IjE3ZUcdnNQz9koECe4O2x3SWD7LSV43pd3CKgyiwwSxWJ4hTBZFIvQ==", + "dev": true, + "requires": { + "@koa/cors": "^3.0.0" + } + }, + "lws-index": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-index/-/lws-index-2.0.0.tgz", + "integrity": "sha512-qfkeQmKYnd13LmQubzI5LtFV2N8PJQG4QvgSoefoiB3dWre9k2T4C7ajjOTKO8mgSzYpUEREduNcQcLyt62n0g==", + "dev": true, + "requires": { + "serve-index-75lb": "^2.0.1" + } + }, + "lws-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-json/-/lws-json-2.0.0.tgz", + "integrity": "sha512-vqUFrAQ5BGpkMS2Mm/ZhgvUMi6Tgia7YtESG7pKjNoiSsD+TxncG0nqp8YjUh2xrEzi/SYFc/ed+9ZOl/t0A0g==", + "dev": true, + "requires": { + "koa-json": "^2.0.2" + } + }, + "lws-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-log/-/lws-log-2.0.0.tgz", + "integrity": "sha512-YveoazSZ0Qb1Tljdm8G8yn9c+mAMXgvLMACZzh5aZIk7p8YJwiXf9r1S+xY7wbXEcKG629KfVO0B5G5gRFcyDQ==", + "dev": true, + "requires": { + "koa-morgan": "^1.0.1", + "stream-log-stats": "^3.0.2" + } + }, + "lws-mime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-mime/-/lws-mime-2.0.0.tgz", + "integrity": "sha512-mfrAgRQ5+hkQ7LJ6EAgwnUeymNeYxwLXZY3UQ6C2hSTr7BqMSzm9k5O0C8wWP2dzdhChzITYKwzWbUnAYVBwtA==", + "dev": true + }, + "lws-range": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lws-range/-/lws-range-3.0.0.tgz", + "integrity": "sha512-7ZhA/LqQnKjolKBo/2BFj9DyDDXcJGY3v05TwYRD0qDGrxW4vuatEjluC3SV7ZO/k4PxDLdxuk+RCgL5t3ThtQ==", + "dev": true, + "requires": { + "koa-range": "^0.3.0" + } + }, + "lws-request-monitor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-request-monitor/-/lws-request-monitor-2.0.0.tgz", + "integrity": "sha512-ZTo0/pS42qiejcYlL+wlpurSbDSS0J7pDDohqBx7jjUQkgni2Qd8cPzn/kW8QI82gXgDmdZH+ps0vheLHlgdgg==", + "dev": true, + "requires": { + "byte-size": "^6.2.0" + } + }, + "lws-rewrite": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lws-rewrite/-/lws-rewrite-3.1.1.tgz", + "integrity": "sha512-cOeaPXIlLUVLxS6BZ52QzZVzI8JjCzlWD4RWizB5Hd+0YGO0SPa3Vgk7CIghtAOsSdjtXg/wSOap2H1h+tw8BQ==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "koa-route": "^3.2.0", + "path-to-regexp": "^6.1.0" + } + }, + "lws-spa": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lws-spa/-/lws-spa-3.0.0.tgz", + "integrity": "sha512-Tz10LfuOTUsRG6z+OCJ/vBN+4LQWoAGIJ1R02CFPrDk0pY3rHezM7/cCpq6Z6dXD+ipdNE8alkVn4zL2M+eVGg==", + "dev": true, + "requires": { + "koa-send": "^5.0.0" + } + }, + "lws-static": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lws-static/-/lws-static-2.0.0.tgz", + "integrity": "sha512-P25A0+IXdkB6Y6gZAG7X0mnaa+FJ8aTiWLUgM5kazaWmruRO7lyhSjitsA3y5TLI3DpPCZn0mWE4SRREujUZLg==", + "dev": true, + "requires": { + "koa-static": "^5.0.0" + } + }, + "marked": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz", + "integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-version-matches": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-version-matches/-/node-version-matches-2.0.1.tgz", + "integrity": "sha512-oqk6+05FC0dNVY5NuXuhPEMq+m1b9ZjS9SIhVE9EjwCHZspnmjSO8npbKAEieinR8GeEgbecoQcYIvI/Kwcf6Q==", + "dev": true, + "requires": { + "semver": "^6.3.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=", + "dev": true + }, + "open": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.1.0.tgz", + "integrity": "sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.1.0.tgz", + "integrity": "sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "qrcode-terminal": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", + "dev": true + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "dev": true + }, + "raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "reduce-flatten": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.0.tgz", + "integrity": "sha512-eczl8wAYBxJ6Egl6I1ECIF+8z6sHu+KE7BzaEDZTpPXKXfy9SUDQlVYwkRcNTjJLC3Iakxbhss50KuT/R6SYfg==", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", + "dev": true, + "requires": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "serve-index-75lb": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/serve-index-75lb/-/serve-index-75lb-2.0.1.tgz", + "integrity": "sha512-/d9r8bqJlFQcwy0a0nb1KnWAA+Mno+V+VaoKocdkbW5aXKRQd/+4bfnRhQRQr6uEoYwTRJ4xgztOyCJvWcpBpQ==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.18", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stream-log-stats": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stream-log-stats/-/stream-log-stats-3.0.2.tgz", + "integrity": "sha512-393j7aeF9iRdHvyANqEQU82UQmpw2CTxgsT83caefh+lOxavVLbVrw8Mr4zjXeZLh2+xeHZMKfVx4T0rJ/EchA==", + "dev": true, + "requires": { + "JSONStream": "^1.3.5", + "ansi-escape-sequences": "^5.1.2", + "byte-size": "^6.2.0", + "common-log-format": "^1.0.0", + "lodash.throttle": "^4.1.1", + "stream-via": "^1.0.4", + "table-layout": "~1.0.0" + } + }, + "stream-slice": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", + "integrity": "sha1-LcT04bk2+xPz6zmi3vGTJ5jQeks=", + "dev": true + }, + "stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true + }, + "streaming-json-stringify": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/streaming-json-stringify/-/streaming-json-stringify-3.1.0.tgz", + "integrity": "sha1-gCAEN6mTzDnE/gAmO3s7kDrIevU=", + "dev": true, + "requires": { + "json-stringify-safe": "5", + "readable-stream": "2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table-layout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.1.tgz", + "integrity": "sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedoc": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.8.tgz", + "integrity": "sha512-/OyrHCJ8jtzu+QZ+771YaxQ9s4g5Z3XsQE3Ma7q+BL392xxBn4UMvvCdVnqKC2T/dz03/VXSLVKOP3lHmDdc/w==", + "dev": true, + "requires": { + "fs-extra": "^8.1.0", + "handlebars": "^4.7.6", + "highlight.js": "^10.0.0", + "lodash": "^4.17.15", + "lunr": "^2.3.8", + "marked": "1.0.0", + "minimatch": "^3.0.0", + "progress": "^2.0.3", + "shelljs": "^0.8.4", + "typedoc-default-themes": "^0.10.2" + } + }, + "typedoc-default-themes": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.10.2.tgz", + "integrity": "sha512-zo09yRj+xwLFE3hyhJeVHWRSPuKEIAsFK5r2u47KL/HBKqpwdUSanoaz5L34IKiSATFrjG5ywmIu98hPVMfxZg==", + "dev": true, + "requires": { + "lunr": "^2.3.8" + } + }, + "typical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", + "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", + "dev": true + }, + "uWebSockets.js": { + "version": "github:uNetworking/uWebSockets.js#3dbec7b56d627193e20705844b6bd10e49848b8c", + "from": "github:uNetworking/uWebSockets.js#v18.4.0", + "dev": true + }, + "uglify-js": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.0.tgz", + "integrity": "sha512-Esj5HG5WAyrLIdYU74Z3JdG2PxdIusvj6IWHMtlyESxc7kcDz7zYlYjpnSokn1UbpV0d/QX9fan7gkCNd/9BQA==", + "dev": true, + "optional": true + }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "walk-back": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz", + "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wordwrapjs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz", + "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==", + "dev": true, + "requires": { + "reduce-flatten": "^2.0.0", + "typical": "^5.0.0" + }, + "dependencies": { + "reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ylru": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", + "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==", + "dev": true + } + } +} diff --git a/src/chains/tezos/package.json b/src/chains/tezos/package.json new file mode 100644 index 0000000000..00a21f3240 --- /dev/null +++ b/src/chains/tezos/package.json @@ -0,0 +1,54 @@ +{ + "name": "@ganache/tezos", + "version": "0.1.0", + "description": "Ganache's Tezos client implementation", + "author": "David Murdoch (https://davidmurdoch.com)", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/chains/tezos#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "source": "src/index.ts", + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "lib" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/chains/tezos" + }, + "scripts": { + "tsc": "ttsc" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ganache-tezos", + "tezos", + "blockchain", + "smart contracts", + "dapps", + "michelson", + "tooling" + ], + "dependencies": { + "@ganache/options": "^0.1.0", + "@ganache/utils": "^0.1.0", + "emittery": "0.7.2" + }, + "devDependencies": { + "@trufflesuite/typedoc-default-themes": "0.6.1", + "cheerio": "1.0.0-rc.3", + "local-web-server": "4.2.1", + "typedoc": "0.17.8", + "uWebSockets.js": "github:uNetworking/uWebSockets.js#v18.4.0" + } +} diff --git a/src/chains/tezos/scripts/post-process-docs.js b/src/chains/tezos/scripts/post-process-docs.js new file mode 100644 index 0000000000..ee20d63e8e --- /dev/null +++ b/src/chains/tezos/scripts/post-process-docs.js @@ -0,0 +1,21 @@ +const cheerio = require("cheerio"); +const { readFileSync, writeFileSync } = require("fs"); +const { randomBytes } = require("crypto"); +const $ = cheerio.load(readFileSync("./lib/docs/classes/_api_.tezosapi.html")); + +$(`.tsd-page-title`).after(``); + +$(".runkit-example").each(function () { + const sanitizedCode = $(this) + .text() + .replace(/;(\s+)/gi, ";\n") + .trim(); + $(this).text(""); + const id = randomBytes(4).toString("hex"); + $(this).attr("id", id).html(); + $(this).prepend( + `` + ); +}); + +writeFileSync("./lib/docs/classes/_api_.tezosapi.html", $.html()); diff --git a/src/chains/tezos/src/api.ts b/src/chains/tezos/src/api.ts new file mode 100644 index 0000000000..9133b66e63 --- /dev/null +++ b/src/chains/tezos/src/api.ts @@ -0,0 +1,9 @@ +import { types } from "@ganache/utils"; + +export default class TezosApi implements types.Api { + readonly [index: string]: (...args: any) => Promise; + + async version(): Promise { + return "just an example"; + } +} diff --git a/src/chains/tezos/src/provider.ts b/src/chains/tezos/src/provider.ts new file mode 100644 index 0000000000..22450f7273 --- /dev/null +++ b/src/chains/tezos/src/provider.ts @@ -0,0 +1,18 @@ +import { types } from "@ganache/utils"; +import TezosApi from "./api"; +import Emittery from "emittery"; + +export default class TezosProvider + extends Emittery.Typed< + { request: types.RequestType }, + "ready" | "close" + > + implements types.Provider { + constructor(providerOptions?: any) { + super(); + this.emit("ready"); + } + public async close() { + this.emit("close"); + } +} diff --git a/src/chains/tezos/tests/index.test.ts b/src/chains/tezos/tests/index.test.ts new file mode 100644 index 0000000000..6ea406bc78 --- /dev/null +++ b/src/chains/tezos/tests/index.test.ts @@ -0,0 +1,7 @@ +"use strict"; + +const tezos = require(".."); + +describe("@ganache/tezos", () => { + it("needs tests"); +}); diff --git a/src/chains/tezos/tsconfig.json b/src/chains/tezos/tsconfig.json new file mode 100644 index 0000000000..25d5c3cf7e --- /dev/null +++ b/src/chains/tezos/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts"] +} diff --git a/src/chains/tezos/typedoc.json b/src/chains/tezos/typedoc.json new file mode 100644 index 0000000000..e38eaed876 --- /dev/null +++ b/src/chains/tezos/typedoc.json @@ -0,0 +1,13 @@ +{ + "name": "@ganache/tezos", + "mode": "modules", + "module": "commonjs", + "theme": "../../../node_modules/@trufflesuite/typedoc-default-themes/bin/default/", + "includeDeclarations": false, + "ignoreCompilerErrors": true, + "preserveConstEnums": true, + "excludeExternals": true, + "categoryOrder": [], + "exclude": ["**/test/*"], + "target": "ES6" +} diff --git a/src/packages/cli/.npmignore b/src/packages/cli/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/packages/cli/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/packages/cli/LICENSE b/src/packages/cli/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/packages/cli/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/packages/cli/README.md b/src/packages/cli/README.md new file mode 100644 index 0000000000..2f34bb6a47 --- /dev/null +++ b/src/packages/cli/README.md @@ -0,0 +1,3 @@ +# `@ganache/cli` + +> TODO: description diff --git a/src/packages/cli/args.ts b/src/packages/cli/args.ts new file mode 100644 index 0000000000..81cd18069c --- /dev/null +++ b/src/packages/cli/args.ts @@ -0,0 +1,258 @@ +import yargs from "yargs"; + +export default function (version: string, isDocker: boolean) { + return yargs + .strict() + .option("p", { + group: "Network:", + alias: "port", + type: "number", + default: 8545, + describe: "Port number to listen on" + }) + .option("h", { + group: "Network:", + alias: ["host", "hostname"], + type: "string", + default: isDocker ? "0.0.0.0" : "127.0.0.1", + describe: "Hostname to listen on" + }) + .option("keepAliveTimeout", { + group: "Network:", + type: "number", + default: 5000, + describe: + "The number of milliseconds of inactivity a server needs to wait for additional incoming data, after it has finished writing the last response, before a socket will be destroyed." + }) + .option("a", { + group: "Accounts:", + alias: "accounts", + describe: "Number of accounts to generate at startup", + type: "number", + default: 10 + }) + .option("e", { + group: "Accounts:", + alias: "defaultBalanceEther", + describe: "Amount of ether to assign each test account", + type: "number", + default: 100.0 + }) + .option("account", { + group: "Accounts:", + describe: + "Account data in the form ',', can be specified multiple times. Note that private keys are 64 characters long and must be entered as an 0x-prefixed hex string. Balance can either be input as an integer, or as a 0x-prefixed hex string with either form specifying the initial balance in wei.", + type: "array", + string: true, + demandOption: false + }) + .option("account_keys_path", { + group: "Accounts:", + alias: "acctKeys", + type: "string", + describe: + "saves generated accounts and private keys as JSON object in specified file", + normalize: true, + demandOption: false, + default: null + }) + .option("n", { + group: "Accounts:", + alias: "secure", + describe: + "Lock available accounts by default (good for third party transaction signing)", + type: "boolean", + default: false + }) + .option("u", { + group: "Accounts:", + alias: "unlock", + type: "array", + string: true, + describe: "Comma-separated list of accounts or indices to unlock", + demandOption: false + }) + .option("k", { + group: "Chain:", + alias: "hardfork", + type: "string", + describe: + "Allows users to specify which hardfork should be used. Supported hardforks are `byzantium`, `constantinople`, `petersburg`, `istanbul` and `muirGlacier` (default).", + default: "muirGlacier" + }) + .option("f", { + group: "Chain:", + alias: "fork", + type: "string", + describe: + "Fork from another currently running Ethereum client at a given block. Input should be the HTTP location and port of the other client, e.g. 'http://localhost:8545' or optionally provide a block number 'http://localhost:8545@1599200'", + default: false + }) + .option("forkCacheSize", { + group: "Chain:", + type: "number", + describe: + "The maximum size, in bytes, of the in-memory cache for queries on a chain fork. Defaults to `1_073_741_824` bytes (1 gigabyte). You can set this to `0` to disable caching (not recommended), or to `-1` for unlimited (will be limited by your node process).", + default: 1073741824 + }) + .option("db", { + group: "Chain:", + describe: "Directory of chain database; creates one if it doesn't exist", + type: "string", + normalize: true, + default: null + }) + .option("s", { + group: "Chain:", + alias: "seed", + type: "string", + describe: "Arbitrary data to generate the HD wallet mnemonic to be used", + defaultDescription: "Random value, unless -d is specified", + conflicts: "d", + demandOption: false + }) + .option("hdPath", { + group: "Accounts:", + alias: "hd_path", + describe: `The hierarchical deterministic path to use when generating accounts. Default: "m/44'/60'/0'/0/"`, + type: "string", + demandOption: false + }) + .option("d", { + group: "Chain:", + alias: "deterministic", + describe: + "Generate deterministic addresses based on a pre-defined mnemonic.", + conflicts: "s", + type: "boolean", + default: undefined, + demandOption: false + }) + .option("m", { + group: "Chain:", + alias: "mnemonic", + type: "string", + describe: + "bip39 mnemonic phrase for generating a PRNG seed, which is in turn used for hierarchical deterministic (HD) account generation", + demandOption: false + }) + .option("noVMErrorsOnRPCResponse", { + group: "Chain:", + describe: + "Do not transmit transaction failures as RPC errors. Enable this flag for error reporting behaviour which is compatible with other clients such as geth and Parity.", + type: "boolean", + default: true + }) + .option("b", { + group: "Chain:", + alias: "blockTime", + type: "number", + describe: + "Block time in seconds for automatic mining. Will instantly mine a new block for every transaction if option omitted. Avoid using unless your test cases require a specific mining interval.", + demandOption: false + }) + .option("i", { + group: "Chain:", + alias: "networkId", + type: "number", + describe: "The Network ID ganache-cli will use to identify itself.", + defaultDescription: + "System time at process start or Network ID of forked blockchain if configured.", + demandOption: false + }) + .option("chainId", { + group: "Chain:", + type: "number", + describe: + "The Chain ID ganache-cli will use for `eth_chainId` RPC and the `CHAINID` opcode.", + defaultDescription: + "For legacy reasons, the default is currently `1337` for `eth_chainId` RPC and `1` for the `CHAINID` opcode. This will be fixed in the next major version of ganache-cli and ganache-core!", + demandOption: false + }) + .option("g", { + group: "Chain:", + alias: "gasPrice", + describe: "The price of gas in wei", + type: "number", + default: 20000000000 + }) + .option("l", { + group: "Chain:", + alias: "gasLimit", + describe: "The block gas limit in wei", + type: "number", + default: 0x6691b7 + }) + .option("callGasLimit", { + group: "Chain:", + describe: + 'Sets the transaction gas limit for `eth_call` and `eth_estimateGas` calls. Must be specified as a hex string. Defaults to "0x1fffffffffffff" (Number.MAX_SAFE_INTEGER)', + type: "number", + default: 0x1fffffffffffff + }) + .option("allowUnlimitedContractSize", { + group: "Chain:", + describe: + "Allows unlimited contract sizes while debugging. By enabling this flag, the check within the EVM for contract size limit of 24KB (see EIP-170) is bypassed. Enabling this flag *will* cause ganache-cli to behave differently than production environments.", + type: "boolean", + default: false + }) + .option("t", { + group: "Chain:", + alias: "time", + describe: + "Date (ISO 8601) that the first block should start. Use this feature, along with the evm_increaseTime method to test time-dependent code.", + type: "string", + coerce: arg => { + let timestamp = Date.parse(arg); + if (isNaN(timestamp)) { + throw new Error("Invalid 'time' format"); + } + return new Date(timestamp); + } + }) + .option("debug", { + group: "Other:", + describe: "Output VM opcodes for debugging", + type: "boolean", + default: false + }) + .option("v", { + group: "Other:", + alias: "verbose", + describe: "Log all requests and responses to stdout", + type: "boolean", + default: false + }) + .option("mem", { + group: "Other:", + describe: "Only show memory output, not tx history", + type: "boolean", + default: false + }) + .option("q", { + group: "Other:", + alias: "quiet", + describe: "Run ganache quietly (no logs)", + type: "boolean", + default: false + }) + .showHelpOnFail(false, "Specify -? or --help for available options") + .help("help") + .alias("help", "?") + .wrap(Math.min(120, yargs.terminalWidth())) + .version(version) + .check(argv => { + if (argv.p < 1 || argv.p > 65535) { + throw new Error(`Invalid port number '${argv.p}'`); + } + + if (argv.h.trim() == "") { + throw new Error( + "Cannot leave hostname blank; please provide a hostname" + ); + } + + return true; + }); +} diff --git a/src/packages/cli/cli.ts b/src/packages/cli/cli.ts new file mode 100644 index 0000000000..45f39e01ce --- /dev/null +++ b/src/packages/cli/cli.ts @@ -0,0 +1,261 @@ +#!/usr/bin/env node + +import Ganache from "./index"; +import { $INLINE_JSON } from "ts-transformer-inline-file"; +import { toChecksumAddress } from "ethereumjs-util"; +import args from "./args"; + +const { version: ganacheVersion } = $INLINE_JSON("../core/package.json"); +const { version } = $INLINE_JSON("./package.json"); +const detailedVersion = + "Ganache CLI v" + version + " (ganache-core: " + ganacheVersion + ")"; + +const isDocker = + "DOCKER" in process.env && process.env.DOCKER.toLowerCase() === "true"; + +const argv = args(detailedVersion, isDocker).argv; + +function parseAccounts(accounts: string[]) { + function splitAccount(account: string) { + const accountParts = account.split(","); + return { + secretKey: accountParts[0], + balance: accountParts[1] + }; + } + + if (typeof accounts === "string") return [splitAccount(accounts)]; + else if (!Array.isArray(accounts)) return; + + var ret = []; + for (var i = 0; i < accounts.length; i++) { + ret.push(splitAccount(accounts[i])); + } + return ret; +} + +if (argv.d) { + argv.s = "TestRPC is awesome!"; // Seed phrase; don't change to Ganache, maintain original determinism +} + +if (typeof argv.unlock == "string") { + argv.unlock = [argv.unlock]; +} + +let logger: { + log: (message?: any, ...optionalParams: any[]) => void; +} = console; + +// If quiet argument passed, no output +if (argv.q === true) { + logger = { + log: function () {} + }; +} + +// If the mem argument is passed, only show memory output, +// not transaction history. +if (argv.mem === true) { + logger = { + log: function () {} + }; + + setInterval(function () { + console.log(process.memoryUsage()); + }, 1000); +} + +var options = { + wallet: { + accountKeysPath: argv.account_keys_path, + mnemonic: argv.m, + seed: argv.s, + totalAccounts: argv.a, + defaultBalance: argv.e, + accounts: parseAccounts(argv.account), + unlockedAccounts: argv.unlock, + secure: argv.n, + hdPath: argv.hdPath + } as any, // any type this because we just pass whatever the user gives us + logging: { + debug: argv.debug, + verbose: argv.v, + logger: logger + }, + miner: { + blockTime: argv.b, + gasPrice: argv.g, + blockGasLimit: argv.l, + callGasLimit: argv.callGasLimit + }, + // forking: { + // fork: argv.f, + // forkCacheSize: argv.forkCacheSize + // }, // TODO + chain: { + hardfork: argv.k, + networkId: argv.i, + vmErrorsOnRPCResponse: !argv.noVMErrorsOnRPCResponse, + allowUnlimitedContractSize: argv.allowUnlimitedContractSize, + time: argv.t, + chainId: argv.chainId, + keepAliveTimeout: argv.keepAliveTimeout + } as any, + database: { + dbPath: argv.db + } +}; + +const server = Ganache.server(options); + +console.log(detailedVersion); + +let started = false; +process.on("uncaughtException", function (e) { + if (started) { + console.log(e); + } else { + console.log(e.stack); + } + process.exit(1); +}); + +// See http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js +if (process.platform === "win32") { + require("readline") + .createInterface({ + input: process.stdin, + output: process.stdout + }) + .on("SIGINT", function () { + process.emit("SIGINT" as any); // TODO: don't abuse process's emit + }); +} + +const closeHandler = async function () { + // graceful shutdown + try { + await server.close(); + process.exit(0); + } catch (err) { + // https://nodejs.org/api/process.html#process_process_exit_code + // writes to process.stdout in Node.js are sometimes asynchronous and may occur over + // multiple ticks of the Node.js event loop. Calling process.exit(), however, forces + // the process to exit before those additional writes to stdout can be performed. + if ((process.stdout as any)._handle) + (process.stdout as any).setBlocking(true); + console.log(err.stack || err); + process.exit(); + } +}; + +process.on("SIGINT", closeHandler); +process.on("SIGTERM", closeHandler); +process.on("SIGHUP", closeHandler); + +async function startGanache(err) { + if (err) { + console.log(err); + return; + } + started = true; + const liveOptions = server.provider.getOptions(); + const accounts = server.provider.getInitialAccounts(); + + console.log(""); + console.log("Available Accounts"); + console.log("=================="); + + var addresses = Object.keys(accounts); + var ethInWei = 1000000000000000000n; + + addresses.forEach(function (address, index) { + var balance = accounts[address].balance; + var strBalance = balance / ethInWei; + var about = balance % ethInWei === 0n ? "" : "~"; + var line = `(${index}) ${toChecksumAddress( + address + )} (${about}${strBalance} ETH)`; + + if (!accounts[address].unlocked) { + line += " 🔒"; + } + + console.log(line); + }); + + console.log(""); + console.log("Private Keys"); + console.log("=================="); + + addresses.forEach(function (address, index) { + console.log("(" + index + ") " + accounts[address].secretKey); + }); + + if (options.wallet.accountKeysPath != null) { + console.log(""); + console.log("Accounts and keys saved to " + options.wallet.accountKeysPath); + } + + if (argv.a == null) { + console.log(""); + console.log("HD Wallet"); + console.log("=================="); + console.log("Mnemonic: " + liveOptions.wallet.mnemonic); + console.log( + "Base HD Path: " + liveOptions.wallet.hdPath + "{account_index}" + ); + } + + if (liveOptions.miner.gasPrice) { + console.log(""); + console.log("Gas Price"); + console.log("=================="); + console.log(liveOptions.miner.gasPrice.toBigInt()); + } + + if (liveOptions.miner.blockGasLimit) { + console.log(""); + console.log("BlockGas Limit"); + console.log("=================="); + console.log(liveOptions.miner.blockGasLimit.toBigInt()); + } + + if (liveOptions.miner.callGasLimit) { + console.log(""); + console.log("Call Gas Limit"); + console.log("=================="); + console.log(liveOptions.miner.callGasLimit.toBigInt()); + } + + // if (options.fork) { + // console.log(""); + // console.log("Forked Chain"); + // console.log("=================="); + // console.log("Location: " + state.blockchain.options.fork); + // console.log( + // "Block: " + to.number(state.blockchain.forkBlockNumber) + // ); + // console.log("Network ID: " + state.net_version); + // console.log( + // "Time: " + (state.blockchain.startTime || new Date()).toString() + // ); + // let maxCacheSize; + // if (options.forkCacheSize === -1) { + // maxCacheSize = "∞"; + // } else { + // maxCacheSize = options.forkCacheSize + " bytes"; + // } + // console.log("Max Cache Size: " + maxCacheSize); + // } + + console.log(""); + console.log("Chain Id"); + console.log("=================="); + console.log(liveOptions.chain.chainId); + + console.log(""); + console.log("Listening on " + argv.h + ":" + argv.p); +} + +server.listen(argv.p, argv.h, startGanache); diff --git a/src/packages/cli/index.ts b/src/packages/cli/index.ts new file mode 100644 index 0000000000..526cebbc45 --- /dev/null +++ b/src/packages/cli/index.ts @@ -0,0 +1,3 @@ +import Ganache from "@ganache/core"; +export { ServerOptions, ProviderOptions } from "@ganache/core"; +export default Ganache; diff --git a/src/packages/cli/npm-shrinkwrap.json b/src/packages/cli/npm-shrinkwrap.json new file mode 100644 index 0000000000..fe02034501 --- /dev/null +++ b/src/packages/cli/npm-shrinkwrap.json @@ -0,0 +1,618 @@ +{ + "name": "@ganache/cli", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "14.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz", + "integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==" + }, + "@types/pbkdf2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/secp256k1": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", + "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "requires": { + "@types/node": "*" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "base-x": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" + }, + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "requires": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "ethereumjs-util": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.7.tgz", + "integrity": "sha512-vU5rtZBlZsgkTw3o6PDKyB8li2EgLavnAbsKcfsH2YhHH1Le+PP8vEiMnAnvgc1B6uMoaM5GDCrVztBw0Q5K9g==", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.4" + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "google-closure-compiler": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20201102.0.1.tgz", + "integrity": "sha512-Cz+1jOswH0MwMVPu1rRH1xD4KYuY5XW2ox5aXwqaAxevqmirhr36f8wgKPHuVRSovFejW640r6UFwyrOT6U0CA==", + "dev": true, + "requires": { + "chalk": "2.x", + "google-closure-compiler-java": "^20201102.0.1", + "google-closure-compiler-linux": "^20201102.0.1", + "google-closure-compiler-osx": "^20201102.0.1", + "google-closure-compiler-windows": "^20201102.0.1", + "minimist": "1.x", + "vinyl": "2.x", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "google-closure-compiler-java": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20201102.0.1.tgz", + "integrity": "sha512-pXJIlyqepHhih0HCbShkAZJyViIxdyd4V7MnCUZEXLIIlygw92e2dC+5XiONDQZgRlF93BPmWCy9jr7wYoW1hQ==", + "dev": true + }, + "google-closure-compiler-linux": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20201102.0.1.tgz", + "integrity": "sha512-aRbyTGnQoFXchcpEFNrP1p/WIvYOgN3hYKI+MOHWkvwVJBY2P8gpb07hAigO8fj+QKD/SFCl+2pXP+JniWOEqw==", + "dev": true, + "optional": true + }, + "google-closure-compiler-osx": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20201102.0.1.tgz", + "integrity": "sha512-VguqEAOYI6XYZN6JcLMP8fpsoXk1Z9YuntMjv0IDVydkbZaHYOI4zE39FJhMuWiN7gOzSX2b/BBC6GsSh1F3fw==", + "dev": true, + "optional": true + }, + "google-closure-compiler-windows": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20201102.0.1.tgz", + "integrity": "sha512-LlynipQi/iP76mjkOu6Rc1mCRuxTAhRvLjq10aGfVjKwpbCAF0Jq2a5k2ygr4xYiINNi2/L2qUw6ObPm9wQCOw==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", + "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", + "requires": { + "bn.js": "^4.11.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + }, + "secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + } + } +} diff --git a/src/packages/cli/package.json b/src/packages/cli/package.json new file mode 100644 index 0000000000..529a50f8fd --- /dev/null +++ b/src/packages/cli/package.json @@ -0,0 +1,58 @@ +{ + "name": "@ganache/cli", + "version": "0.1.0", + "description": "", + "author": "David Murdoch", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/packages/cli#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "source": "index.ts", + "bin": { + "ganache": "./lib/cli.js", + "ganache-cli": "./lib/cli.js" + }, + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "lib" + ], + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/packages/cli" + }, + "scripts": { + "tsc": "ttsc", + "test": "nyc npm run mocha", + "mocha": "cross-env TS_NODE_COMPILER=ttypescript TS_NODE_FILES=true mocha --exit --check-leaks --throw-deprecation --trace-warnings --require ts-node/register 'tests/**/*.test.ts'" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ganache-cli", + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling", + "truffle" + ], + "devDependencies": { + "@ganache/core": "^0.1.0", + "google-closure-compiler": "20201102.0.1" + }, + "dependencies": { + "@types/node": "14.14.6", + "ethereumjs-util": "^7.0.7" + } +} diff --git a/src/packages/cli/tests/index.test.ts b/src/packages/cli/tests/index.test.ts new file mode 100644 index 0000000000..e853595762 --- /dev/null +++ b/src/packages/cli/tests/index.test.ts @@ -0,0 +1,6 @@ +import assert from "assert"; +import cli from ".."; + +describe("@ganache/cli", () => { + it("needs tests"); +}); diff --git a/src/packages/cli/tsconfig.json b/src/packages/cli/tsconfig.json new file mode 100644 index 0000000000..081b4a87ef --- /dev/null +++ b/src/packages/cli/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts", "cli.ts"] +} diff --git a/src/packages/core/.npmignore b/src/packages/core/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/packages/core/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/packages/core/LICENSE b/src/packages/core/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/packages/core/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/packages/core/README.md b/src/packages/core/README.md new file mode 100644 index 0000000000..9ae51677af --- /dev/null +++ b/src/packages/core/README.md @@ -0,0 +1,5 @@ +# `@ganache/core` + +The `ganache-core` npm package. + +See [README.md](../../../README.md) for info. diff --git a/src/packages/core/index.ts b/src/packages/core/index.ts new file mode 100644 index 0000000000..debc6e2150 --- /dev/null +++ b/src/packages/core/index.ts @@ -0,0 +1,11 @@ +import Connector from "./src/connector"; +import { ProviderOptions, ServerOptions } from "./src/options"; +import Server from "./src/server"; + +export { ProviderOptions, ServerOptions } from "./src/options"; + +export default { + server: (options?: ServerOptions) => new Server(options), + provider: (options?: ProviderOptions) => + Connector.initialize(options).provider +}; diff --git a/src/packages/core/npm-shrinkwrap.json b/src/packages/core/npm-shrinkwrap.json new file mode 100644 index 0000000000..d73c4cc56d --- /dev/null +++ b/src/packages/core/npm-shrinkwrap.json @@ -0,0 +1,207 @@ +{ + "name": "@ganache/core", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, + "@types/node": { + "version": "14.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz", + "integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==", + "dev": true + }, + "@types/superagent": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.10.tgz", + "integrity": "sha512-xAgkb2CMWUMCyVc/3+7iQfOEBE75NvuZeezvmixbUw3nmENf2tCnQkW5yQLTYqvXUQ+R6EXxdqKKbal2zM5V/g==", + "dev": true, + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true + }, + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "superagent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", + "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", + "dev": true, + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" + } + }, + "uWebSockets.js": { + "version": "github:uNetworking/uWebSockets.js#3dbec7b56d627193e20705844b6bd10e49848b8c", + "from": "github:uNetworking/uWebSockets.js#v18.4.0" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "dev": true + } + } +} diff --git a/src/packages/core/package.json b/src/packages/core/package.json new file mode 100644 index 0000000000..8fdc8eb0c6 --- /dev/null +++ b/src/packages/core/package.json @@ -0,0 +1,61 @@ +{ + "name": "@ganache/core", + "version": "0.1.0", + "description": "A library to create a local blockchain for fast Ethereum development.", + "author": "David Murdoch (https://davidmurdoch.com)", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/packages/core#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "source": "index.ts", + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "lib" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/packages/core" + }, + "scripts": { + "tsc": "ttsc", + "test": "nyc npm run mocha", + "mocha": "cross-env TS_NODE_COMPILER=ttypescript TS_NODE_FILES=true mocha --exit --throw-deprecation --trace-warnings --check-leaks --require ts-node/register 'tests/**/*.test.ts'" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ganache-core", + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling" + ], + "dependencies": { + "@ganache/ethereum": "^0.1.0", + "@ganache/flavors": "^0.1.0", + "@ganache/options": "^0.1.0", + "@ganache/tezos": "^0.1.0", + "@ganache/utils": "^0.1.0", + "uWebSockets.js": "github:uNetworking/uWebSockets.js#v18.4.0" + }, + "devDependencies": { + "@types/superagent": "4.1.10", + "superagent": "6.1.0", + "ws": "7.3.1" + } +} diff --git a/src/packages/core/src/@types/superagent.d.ts b/src/packages/core/src/@types/superagent.d.ts new file mode 100644 index 0000000000..f1211cd567 --- /dev/null +++ b/src/packages/core/src/@types/superagent.d.ts @@ -0,0 +1,6 @@ +// superagent TS def has issues with these browser APIs not being available in +// node. +// error TS2304: Cannot find name 'XMLHttpRequest' +declare interface XMLHttpRequest {} +// error TS2304: Cannot find name 'Blob' +declare interface Blob {} diff --git a/src/packages/core/src/@types/uWebsockets.js.ts b/src/packages/core/src/@types/uWebsockets.js.ts new file mode 100644 index 0000000000..21eb947df8 --- /dev/null +++ b/src/packages/core/src/@types/uWebsockets.js.ts @@ -0,0 +1,23 @@ +import "uWebSockets.js"; + +enum ListenOptions { + LIBUS_LISTEN_DEFAULT = 0, + LIBUS_LISTEN_EXCLUSIVE_PORT = 1 +} +// uWebSockets.js doesn't include these in its TS def file. +declare module "uWebSockets.js" { + export interface TemplatedApp { + listen( + host: RecognizedString, + port: number, + options: ListenOptions, + cb: (listenSocket: us_listen_socket | false) => void + ): TemplatedApp; + + listen( + port: number, + options: ListenOptions, + cb: (listenSocket: us_listen_socket | false) => void + ): TemplatedApp; + } +} diff --git a/src/packages/core/src/connector.ts b/src/packages/core/src/connector.ts new file mode 100644 index 0000000000..d8203b89f2 --- /dev/null +++ b/src/packages/core/src/connector.ts @@ -0,0 +1,45 @@ +import { utils } from "@ganache/utils"; +import { ConnectorsByName, DefaultFlavor } from "@ganache/flavors"; +import { Options as ProviderOptions } from "@ganache/flavors"; +import { hasOwn } from "@ganache/utils/src/utils"; + +/** + * Loads the connector specified by the given `flavor` + */ +export default { + initialize: ( + providerOptions: ProviderOptions = { + flavor: DefaultFlavor, + chain: { asyncRequestProcessing: true } + } + ) => { + const flavor = providerOptions.flavor || DefaultFlavor; + + // Set up our request coordinator to either use FIFO or or async request processing. + // The RequestCoordinator _can_ be used to coordinate the number of requests being processed, but we don't use it + // for that (yet), instead of "all" (0) or just 1 as we are doing here: + const asyncRequestProcessing = + "chain" in providerOptions + ? providerOptions.chain.asyncRequestProcessing + : (providerOptions as any).asyncRequestProcessing; + const requestCoordinator = new utils.RequestCoordinator( + asyncRequestProcessing ? 0 : 1 + ); + + // The Executor is responsible for actually executing the method on the chain/API. + // It performs some safety checks to ensure "safe" method execution before passing it + // to a RequestCoordinator. + const executor = new utils.Executor(requestCoordinator); + + const connector = new ConnectorsByName[flavor]( + providerOptions as any, + executor + ); + + // The request coordinator is initialized in a "paused" state; when the provider is ready we unpause. + // This lets us accept queue requests before we've even fully initialized. + connector.on("ready", requestCoordinator.resume); + + return connector; + } +}; diff --git a/src/packages/core/src/options/index.ts b/src/packages/core/src/options/index.ts new file mode 100644 index 0000000000..b36205c05c --- /dev/null +++ b/src/packages/core/src/options/index.ts @@ -0,0 +1,36 @@ +import { Options as FlavorOptions } from "@ganache/flavors"; +import { ServerConfig, ServerOptions } from "./server-options"; +import { + Defaults, + Definitions, + ExternalConfig, + InternalConfig, + OptionsConfig +} from "@ganache/options"; + +export type ProviderOptions = FlavorOptions; + +export type Options = { + server: ServerConfig; +}; + +export type ServerOptions = Partial< + { + [K in keyof Options]: ExternalConfig; + } +> & + ProviderOptions; + +export type InternalOptions = { + [K in keyof Options]: InternalConfig; +}; + +export type ServerDefaults = { + [K in keyof Options]: Definitions; +}; + +export const serverDefaults: Defaults = { + server: ServerOptions +}; + +export const serverOptionsConfig = new OptionsConfig(serverDefaults); diff --git a/src/packages/core/src/options/server-options.ts b/src/packages/core/src/options/server-options.ts new file mode 100644 index 0000000000..02d2015bbf --- /dev/null +++ b/src/packages/core/src/options/server-options.ts @@ -0,0 +1,67 @@ +import { Definitions } from "@ganache/options"; + +export type ServerConfig = { + options: { + /** + * Enable a websocket server. This is `true` by default. + * + * @default true + */ + readonly ws: { + type: boolean; + hasDefault: true; + legacy: { + /** + * @deprecated Use server.ws instead. + */ + ws: boolean; + }; + }; + + /** + * Wether or not websockets should response with binary data (ArrayBuffers) or + * strings. + * + * Default is "auto", which responds using the same format as the incoming + * message that triggered the response. + * + * @default "auto" + */ + readonly wsBinary: { + type: boolean | "auto"; + hasDefault: true; + }; + + /** + * @obsolete Option removed in v3 + */ + readonly keepAliveTimeout: { + type: void; + legacy: { + /** + * @obsolete Option removed in v3 + */ + keepAliveTimeout: void; + }; + }; + }; +}; +const normalize = (rawInput: T) => rawInput; + +export const ServerOptions: Definitions = { + ws: { + normalize, + default: () => true, + legacyName: "ws" + }, + wsBinary: { + normalize, + default: () => "auto" + }, + keepAliveTimeout: { + normalize: () => { + throw new Error("`keepAliveTimeout` was removed in v3"); + }, + legacyName: "keepAliveTimeout" + } +}; diff --git a/src/packages/core/src/server.ts b/src/packages/core/src/server.ts new file mode 100644 index 0000000000..226297f28e --- /dev/null +++ b/src/packages/core/src/server.ts @@ -0,0 +1,172 @@ +import { InternalOptions, ServerOptions, serverOptionsConfig } from "./options"; + +import uWS, { TemplatedApp, us_listen_socket } from "uWebSockets.js"; +import { Connectors } from "@ganache/flavors"; +import Connector from "./connector"; +import WebsocketServer, { WebSocketCapableFlavor } from "./servers/ws-server"; +import HttpServer from "./servers/http-server"; + +type Providers = Connectors["provider"]; + +const DEFAULT_HOST = "127.0.0.1"; + +type Callback = (err: Error | null) => void; + +/** + * Server ready state constants. + * + * These are bit flags. This means that you can check if the status is: + * * open: `status === Status.open` + * * opening: `status === Status.opening` + * * open || opening: `status & Status.open !== 0` or `status & Status.opening !== 0` + * * closed: `status === Status.closed` + * * closing: `status === Status.closing` + * * open || closing: `status & Status.closed !== 0` or `status & Status.closing !== 0` + */ +export enum Status { + /** + * The connection is open and ready to communicate. + */ + open = 1, + /** + * The connection is not yet open. + */ + opening = 3, + /** + * The connection is closed. + */ + closed = 4, + /** + * The connection is in the process of closing. + */ + closing = 12 +} + +export default class Server { + #app: TemplatedApp; + #httpServer: HttpServer; + #listenSocket?: us_listen_socket; + #options: InternalOptions; + #connector: Connectors; + #status = Status.closed; + #websocketServer: WebsocketServer | null = null; + + public get provider(): Providers { + return this.#connector.provider; + } + + public get status() { + return this.#status; + } + + constructor(serverOptions: ServerOptions = { flavor: "ethereum" }) { + const opts = (this.#options = serverOptionsConfig.normalize(serverOptions)); + const connector = (this.#connector = Connector.initialize(serverOptions)); + + const _app = (this.#app = uWS.App()); + + if (this.#options.server.ws) { + this.#websocketServer = new WebsocketServer( + _app, + connector as WebSocketCapableFlavor, + opts.server + ); + } + this.#httpServer = new HttpServer(_app, connector); + } + + listen(port: number): Promise; + listen(port: number, host: string): Promise; + listen(port: number, callback: Callback): void; + listen(port: number, host: string, callback: Callback): void; + listen( + port: number, + host?: string | Callback, + callback?: Callback + ): void | Promise { + let hostname: string = null; + if (typeof host === "function") { + callback = host; + hostname = null; + } + const callbackIsFunction = typeof callback === "function"; + const status = this.#status; + if (status === Status.closing) { + // if closing + const err = new Error(`Cannot start server while it is closing.`); + return callbackIsFunction + ? process.nextTick(callback!, err) + : Promise.reject(err); + } else if (status & Status.open) { + // if open or opening + const err = new Error(`Server is already open on port: ${port}.`); + return callbackIsFunction + ? process.nextTick(callback!, err) + : Promise.reject(err); + } + + this.#status = Status.opening; + + const promise = new Promise( + (resolve: (listenSocket: false | uWS.us_listen_socket) => void) => { + // Make sure we have *exclusive* use of this port. + // https://github.com/uNetworking/uSockets/commit/04295b9730a4d413895fa3b151a7337797dcb91f#diff-79a34a07b0945668e00f805838601c11R51 + const LIBUS_LISTEN_EXCLUSIVE_PORT = 1; + hostname + ? (this.#app as any).listen( + hostname, + port, + LIBUS_LISTEN_EXCLUSIVE_PORT, + resolve + ) + : this.#app.listen(port as any, LIBUS_LISTEN_EXCLUSIVE_PORT, resolve); + } + ).then(listenSocket => { + if (listenSocket) { + this.#status = Status.open; + this.#listenSocket = listenSocket; + if (callbackIsFunction) callback!(null); + } else { + this.#status = Status.closed; + const err = new Error( + `listen EADDRINUSE: address already in use ${ + hostname || DEFAULT_HOST + }:${port}.` + ); + if (callbackIsFunction) callback!(err); + else throw err; + } + }); + + if (!callbackIsFunction) { + return promise; + } + } + + public async close() { + if (this.#status === Status.opening) { + // if opening + throw new Error(`Cannot close server while it is opening.`); + } else if (this.#status & Status.closed) { + // if closed or closing + throw new Error(`Server is already closed or closing.`); + } + + const _listenSocket = this.#listenSocket; + this.#status = Status.closing; + this.#listenSocket = void 0; + // close the socket to prevent any more connections + uWS.us_listen_socket_close(_listenSocket); + // close all the connected websockets: + const ws = this.#websocketServer; + if (ws) { + ws.close(); + } + + // and do all http cleanup, if any + this.#httpServer.close(); + await this.#connector.close(); + this.#status = Status.closed; + this.#app = void 0; + } +} diff --git a/src/packages/core/src/servers/http-server.ts b/src/packages/core/src/servers/http-server.ts new file mode 100644 index 0000000000..481f2321ed --- /dev/null +++ b/src/packages/core/src/servers/http-server.ts @@ -0,0 +1,216 @@ +import { + TemplatedApp, + HttpResponse, + HttpRequest, + RecognizedString +} from "uWebSockets.js"; +import ContentTypes from "./utils/content-types"; +import HttpResponseCodes from "./utils/http-response-codes"; +import { Connectors } from "@ganache/flavors"; + +type HttpMethods = "GET" | "OPTIONS" | "POST"; + +const noop = () => {}; + +/** + * uWS doesn't let us use the request after the request method has completed. + * But we can't set headers until after the statusCode is set. But we don't + * know the status code until the provider returns asynchronously. + * So this does request-related work immediately and returns a function to do the + * rest of the work later. + * @param method + * @param request + */ +function prepareCORSResponseHeaders(method: HttpMethods, request: HttpRequest) { + // https://fetch.spec.whatwg.org/#http-requests + const origin = request.getHeader("origin"); + const acrh = request.getHeader("access-control-request-headers"); + return (response: HttpResponse) => { + const isCORSRequest = origin !== ""; + if (isCORSRequest) { + // OPTIONS preflight requests need a little extra treatment + if (method === "OPTIONS") { + // we only allow POST requests, so it doesn't matter which method the request is asking for + response.writeHeader("Access-Control-Allow-Methods", "POST"); + // echo all requested access-control-request-headers back to the response + if (acrh !== "") { + response.writeHeader("Access-Control-Allow-Headers", acrh); + } + + // Make browsers and compliant clients cache the OPTIONS preflight response for 10 + // minutes (this is the maximum time Chromium allows) + response.writeHeader("Access-Control-Max-Age", "600"); // seconds + } + + // From the spec: https://fetch.spec.whatwg.org/#http-responses + // "For a CORS-preflight request, request’s credentials mode is always "omit", + // but for any subsequent CORS requests it might not be. Support therefore + // needs to be indicated as part of the HTTP response to the CORS-preflight request as well.", so this + // header is added to all requests. + // Additionally, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials, + // states that there aren't any HTTP Request headers that indicate you whether or not Request.withCredentials + // is set. Because web3@1.0.0-beta.35-? always sets `request.withCredentials = true` while Safari requires it be + // returned even when no credentials are set in the browser this header must always be return on all requests. + // (I've found that Chrome and Firefox don't actually require the header when credentials aren't set) + // Regression Commit: https://github.com/ethereum/web3.js/pull/1722 + // Open Web3 Issue: https://github.com/ethereum/web3.js/issues/1802 + response.writeHeader("Access-Control-Allow-Credentials", "true"); + + // From the spec: "It cannot be reliably identified as participating in the CORS protocol + // as the `Origin` header is also included for all requests whose method is neither + // `GET` nor `HEAD`." + // Explicitly set the origin instead of using *, since credentials + // can't be used in conjunction with *. This will always be set + /// for valid preflight requests. + response.writeHeader("Access-Control-Allow-Origin", origin); + } + }; +} + +function sendResponse( + response: HttpResponse, + statusCode: HttpResponseCodes, + contentType?: RecognizedString, + data?: RecognizedString, + writeHeaders: (response: HttpResponse) => void = noop +): void { + response.cork(() => { + response.writeStatus(statusCode); + writeHeaders(response); + if (contentType) { + response.writeHeader("Content-Type", contentType); + } + response.end(data); + }); +} + +export default class HttpServer { + #connector: Connectors; + constructor(app: TemplatedApp, connector: Connectors) { + this.#connector = connector; + + // JSON-RPC routes... + app.post("/", this.#handlePost).options("/", this.#handleOptions); + + // because Easter Eggs are fun... + app.get("/418", response => { + sendResponse( + response, + HttpResponseCodes.IM_A_TEAPOT, + ContentTypes.PLAIN, + "418 I'm a teapot" + ); + }); + + // fallback routes... + app.any("/*", (response, request) => { + const connectionHeader = request.getHeader("connection"); + if (connectionHeader && connectionHeader.toLowerCase() === "upgrade") { + // if we got here it means the websocket server wasn't enabled but + // a client tried to connect via websocket. This is a Bad Request. + sendResponse( + response, + HttpResponseCodes.BAD_REQUEST, + ContentTypes.PLAIN, + "400 Bad Request" + ); + } else { + // all other requests don't mean anything to us, so respond with `404 NOT FOUND`... + sendResponse( + response, + HttpResponseCodes.NOT_FOUND, + ContentTypes.PLAIN, + "404 Not Found" + ); + } + }); + } + + #handlePost = (response: HttpResponse, request: HttpRequest) => { + // handle JSONRPC post requests... + const writeHeaders = prepareCORSResponseHeaders("POST", request); + + // TODO(perf): pre-allocate the buffer if we know the Content-Length + let buffer: Buffer; + let aborted = false; + response.onAborted(() => { + aborted = true; + }); + response.onData((message: ArrayBuffer, isLast: boolean) => { + const chunk = Buffer.from(message); + if (isLast) { + const connector = this.#connector; + let payload: ReturnType; + try { + const message = buffer ? Buffer.concat([buffer, chunk]) : chunk; + payload = connector.parse(message); + } catch (e) { + sendResponse( + response, + HttpResponseCodes.BAD_REQUEST, + ContentTypes.PLAIN, + "400 Bad Request: " + e.message, + writeHeaders + ); + return; + } + + connector + .handle(payload, request) + .then(({ value }) => value) + .then(result => { + if (aborted) { + // if the request has been aborted don't try sending (it'll + // cause an `Unhandled promise rejection` if we try) + return; + } + const data = connector.format(result, payload); + sendResponse( + response, + HttpResponseCodes.OK, + ContentTypes.JSON, + data, + writeHeaders + ); + }) + .catch(error => { + if (aborted) { + // if the request has been aborted don't try sending (it'll + // cause an `Unhandled promise rejection` if we try) + return; + } + const data = connector.formatError(error, payload); + sendResponse( + response, + HttpResponseCodes.OK, + ContentTypes.JSON, + data, + writeHeaders + ); + }); + } else { + if (buffer) { + buffer = Buffer.concat([buffer, chunk]); + } else { + buffer = Buffer.concat([chunk]); + } + } + }); + }; + + #handleOptions = (response: HttpResponse, request: HttpRequest) => { + // handle CORS preflight requests... + const writeHeaders = prepareCORSResponseHeaders("OPTIONS", request); + // OPTIONS responses don't have a body, so respond with `204 No Content`... + sendResponse( + response, + HttpResponseCodes.NO_CONTENT, + void 0, + "", + writeHeaders + ); + }; + public close() { + // currently a no op. + } +} diff --git a/src/packages/core/src/servers/utils/content-types.ts b/src/packages/core/src/servers/utils/content-types.ts new file mode 100644 index 0000000000..debf586fc9 --- /dev/null +++ b/src/packages/core/src/servers/utils/content-types.ts @@ -0,0 +1,5 @@ +enum ContentTypes { + PLAIN = "text/plain", + JSON = "application/json" +} +export default ContentTypes; diff --git a/src/packages/core/src/servers/utils/http-response-codes.ts b/src/packages/core/src/servers/utils/http-response-codes.ts new file mode 100644 index 0000000000..d0deaa7dad --- /dev/null +++ b/src/packages/core/src/servers/utils/http-response-codes.ts @@ -0,0 +1,9 @@ +enum HttpResponseCodes { + OK = "200", + NO_CONTENT = "204", + BAD_REQUEST = "400", + NOT_FOUND = "404", + METHOD_NOT_ALLOWED = "405", + IM_A_TEAPOT = "418" +} +export default HttpResponseCodes; diff --git a/src/packages/core/src/servers/utils/websocket-close-codes.ts b/src/packages/core/src/servers/utils/websocket-close-codes.ts new file mode 100644 index 0000000000..f4fac84005 --- /dev/null +++ b/src/packages/core/src/servers/utils/websocket-close-codes.ts @@ -0,0 +1,11 @@ +enum WebSocketCloseCodes { + // CLOSE_NORMAL = 1000, + /** + * Indicates that an endpoint is "going away", such as a server going down or + * a browser having navigated away from a page. + */ + CLOSE_GOING_AWAY = 1001 + // CLOSE_PROTOCOL_ERROR = 1002, + // CLOSE_ABNORMAL = 1006 +} +export default WebSocketCloseCodes; diff --git a/src/packages/core/src/servers/ws-server.ts b/src/packages/core/src/servers/ws-server.ts new file mode 100644 index 0000000000..792da2d0e3 --- /dev/null +++ b/src/packages/core/src/servers/ws-server.ts @@ -0,0 +1,123 @@ +import uWS, { TemplatedApp, WebSocket } from "uWebSockets.js"; +import WebSocketCloseCodes from "./utils/websocket-close-codes"; +import { ServerOptions } from "../options"; +import * as Flavors from "@ganache/flavors"; +import { PromiEvent } from "@ganache/utils"; + +type MergePromiseT = Promise ? X : never>; + +type HandlesWebSocketSignature = (payload: any, connection: WebSocket) => any; + +type WebSocketCapableFlavorMap = { + [k in keyof Flavors.ConnectorsByName]: Flavors.ConnectorsByName[k]["handle"] extends HandlesWebSocketSignature + ? Flavors.ConnectorsByName[k] + : never; +}; + +export type WebSocketCapableFlavor = { + [k in keyof WebSocketCapableFlavorMap]: WebSocketCapableFlavorMap[k]; +}[keyof WebSocketCapableFlavorMap]; + +export type GanacheWebSocket = WebSocket & { closed?: boolean }; + +export type WebsocketServerOptions = Pick; + +export default class WebsocketServer { + #connections = new Map void>>(); + constructor( + app: TemplatedApp, + connector: WebSocketCapableFlavor, + options: WebsocketServerOptions + ) { + const connections = this.#connections; + const wsBinary = options.wsBinary; + const autoBinary = wsBinary === "auto"; + app.ws("/", { + /* WS Options */ + compression: uWS.SHARED_COMPRESSOR, // Zero memory overhead compression + maxPayloadLength: 16 * 1024, // 128 Kibibits + idleTimeout: 120, // in seconds + + /* Handlers */ + open: (ws: GanacheWebSocket) => { + ws.closed = false; + connections.set(ws, new Set()); + }, + + message: async ( + ws: GanacheWebSocket, + message: ArrayBuffer, + isBinary: boolean + ) => { + let payload: ReturnType; + const useBinary = autoBinary ? isBinary : (wsBinary as boolean); + try { + payload = connector.parse(Buffer.from(message)); + } catch (err) { + const response = connector.formatError(err, payload); + ws.send(response, useBinary, true); + return; + } + + let response: uWS.RecognizedString; + + try { + const { value } = await connector.handle(payload, ws); + + // The socket may have closed while we were waiting for the response + // Don't bother trying to send to it if it was. + if (ws.closed) return; + + const resultEmitter = value as MergePromiseT; + const result = await resultEmitter; + if (ws.closed) return; + + response = connector.format(result, payload); + + // if the result is an emitter listen to its `"message"` event + if (resultEmitter instanceof PromiEvent) { + resultEmitter.on("message", (result: any) => { + // note: we _don't_ need to check if `ws.closed` here because when + // `ws.closed` is set we remove this event handler anyway. + const message = JSON.stringify({ + jsonrpc: "2.0", + method: result.type, + params: result.data + }); + ws.send(message, isBinary, true); + }); + + // keep track of listeners to dispose off when the ws disconnects + connections.get(ws).add(resultEmitter.dispose); + } + } catch (err) { + // ensure the connector's `handle` fn doesn't throw outside of a Promise + + if (ws.closed) return; + response = connector.formatError(err, payload); + } + + ws.send(response, useBinary, true); + }, + + drain: (ws: WebSocket) => { + // This is there so tests can detect if a small amount of backpressure + // is happening and that things will still work if it does. We actually + // don't do anything to manage excessive backpressure. + // TODO: handle back pressure for real! + // options.logger.log("WebSocket backpressure: " + ws.getBufferedAmount()); + }, + + close: (ws: GanacheWebSocket) => { + ws.closed = true; + connections.get(ws).forEach(dispose => dispose()); + connections.delete(ws); + } + }); + } + close() { + this.#connections.forEach((_, ws) => + ws.end(WebSocketCloseCodes.CLOSE_GOING_AWAY, "Server closed by client") + ); + } +} diff --git a/src/packages/core/tests/connector.test.ts b/src/packages/core/tests/connector.test.ts new file mode 100644 index 0000000000..4828110351 --- /dev/null +++ b/src/packages/core/tests/connector.test.ts @@ -0,0 +1,148 @@ +import assert from "assert"; +import Ganache from "../"; +import { Provider as EthereumProvider } from "@ganache/ethereum"; + +describe("connector", () => { + it("works without passing options", async () => { + assert.doesNotThrow(() => Ganache.provider()); + }); + + it("it logs when `options.verbose` is `true`", async () => { + const logger = { log: (_msg: string) => {} }; + const p = Ganache.provider({ logging: { logger, verbose: true } }); + + logger.log = msg => { + assert.strictEqual( + msg, + " > net_version: undefined", + "doesn't work when no params" + ); + }; + await p.send("net_version"); + + return new Promise(async resolve => { + logger.log = msg => { + const expected = + " > web3_sha3: [\n" + ' > "Tim is a swell guy."\n' + " > ]"; + assert.strictEqual(msg, expected, "doesn't work with params"); + resolve(); + }; + await p.send("web3_sha3", ["Tim is a swell guy."]); + }); + }); + + it("it processes requests asyncronously when `asyncRequestProcessing` is default (true)", async () => { + const p = Ganache.provider(); + const accounts = await p.send("eth_accounts"); + // `eth_accounts` should always be faster than eth_getBalance; eth_accounts + // should return before eth_getBalance because of the + // `asyncRequestProcessing` flag. + const calA = p.send("eth_getBalance", [accounts[0]]); + const callB = p.send("eth_accounts"); + const result = await Promise.race([calA, callB]); + assert(Array.isArray(result)); + assert.strictEqual(result.length, 10); + }); + + it("it processes requests syncronously when `asyncRequestProcessing` is `false`", async () => { + const p = Ganache.provider({ chain: { asyncRequestProcessing: false } }); + const accounts = await p.send("eth_accounts"); + // eth_getBalance should return first even though eth_accounts is faster; + // eth_getBalance should return before eth_accounts because of the + // `asyncRequestProcessing` flag. + const calA = p.send("eth_getBalance", [accounts[0]]); + const callB = p.send("eth_accounts"); + const result = await Promise.race([calA, callB]); + assert.strictEqual(result, "0x56bc75e2d63100000"); + }); + + // duck punch a property that shouldn't appear on the API. we test this + // to make sure that 3rd party API implementations can't shoot themselves + // in the foot on accident + it.skip("TODO: allow 'injecting' our own engine or API into a provider!", async () => { + const p = Ganache.provider(); + // this won't work becase ganache uses _real_ private properties that can't + // be duck punched. This test is supposed to ensure that _real_ non-function + // own properties (and __proto__ properties) can't be executed. + (p as any)._engine._api.__proto__.illegalProperty = true; + await assert.rejects(p.send("illegalProperty" as any, []), { + message: "`The method illegalProperty does not exist/is not available`" + }); + }); + + it("rejects invalid rpc methods", async () => { + const p = Ganache.provider(); + + const illegalMethodNames = [ + "toString", + "toValue", + "__proto__", + "prototype", + "notAFunction", + "", + " ", + "constructor" + ] as const; + await Promise.all( + illegalMethodNames.map(methodName => { + assert.rejects(() => p.send(methodName as any), { + message: `The method ${methodName} does not exist/is not available` + }); + }) + ); + + // make sure we reject non-strings over the classical send interface + const circular: any = {}; + circular.circular = circular; + const illegalMethodTypes = [ + 123, + // just cast as string to make TS let me test weird stuff... + (Buffer.from([1]) as unknown) as string, + null, + void 0, + {}, + [], + { foo: "bar" }, + [1, 2], + new Date(), + Infinity, + NaN, + circular + ] as const; + await Promise.all( + illegalMethodTypes.map(method => { + return assert.rejects( + new Promise((resolve, reject) => { + p.send( + { + id: "1", + jsonrpc: "2.0", + method + }, + (err, result): void => { + if (err) { + reject(err); + } else { + resolve(result); + } + } + ); + }), + { + message: `The method ${method} does not exist/is not available` + } + ); + }) + ); + + // make sure we reject non-strings over the legacy send interface + illegalMethodTypes.map(methodType => { + assert.throws(() => p.send(methodType), { + message: + "No callback provided to provider's send function. As of " + + "web3 1.0, provider.send is no longer synchronous and must be " + + "passed a callback as its final argument." + }); + }); + }); +}); diff --git a/src/packages/core/tests/helpers/getProvider.ts b/src/packages/core/tests/helpers/getProvider.ts new file mode 100644 index 0000000000..01a35543be --- /dev/null +++ b/src/packages/core/tests/helpers/getProvider.ts @@ -0,0 +1,13 @@ +import Ganache from "../../src/"; +import { ProviderOptions } from "@ganache/options"; +import { EthereumProvider } from "@ganache/ethereum"; + +const mnemonic = + "into trim cross then helmet popular suit hammer cart shrug oval student"; +const getProvider = ( + options: ProviderOptions = { flavor: "ethereum", mnemonic } +) => { + return Ganache.provider(options) as EthereumProvider; +}; + +export default getProvider; diff --git a/src/packages/core/tests/interface.test.ts b/src/packages/core/tests/interface.test.ts new file mode 100644 index 0000000000..ad9f658680 --- /dev/null +++ b/src/packages/core/tests/interface.test.ts @@ -0,0 +1,16 @@ +import Ganache from ".."; +import * as assert from "assert"; + +describe("interface", () => { + it("has an interface", () => { + assert.ok(Ganache.server); + assert.ok(Ganache.provider); + assert.strictEqual(Object.keys(Ganache).length, 2); + + // in v3 these two properties were *removed* because it was confusing. + // these tests are kinda unncessary, but I just want to intent to be + // explicit. + assert.strictEqual("Server" in Ganache, false); + assert.strictEqual("Provider" in Ganache, false); + }); +}); diff --git a/src/packages/core/tests/server.test.ts b/src/packages/core/tests/server.test.ts new file mode 100644 index 0000000000..50897ef5de --- /dev/null +++ b/src/packages/core/tests/server.test.ts @@ -0,0 +1,881 @@ +import Ganache from "../"; +import * as assert from "assert"; +import request from "superagent"; +import WebSocket from "ws"; +import Server, { Status } from "../src/server"; +import http from "http"; +// https://github.com/sindresorhus/into-stream/releases/tag/v6.0.0 +import intoStream = require("into-stream"); +import { PromiEvent } from "@ganache/utils"; +import { promisify } from "util"; +import { ServerOptions } from "../src/options"; + +const IS_WINDOWS = process.platform === "win32"; + +describe("server", () => { + const port = 5234; + const networkId = 1234; + const jsonRpcJson: any = { + jsonrpc: "2.0", + id: "1", + method: "net_version", + params: [] + }; + const logger = { + log: (_message: string) => {} + }; + let s: Server; + + async function setup( + options: ServerOptions = { + chain: { + networkId + }, + logging: { + logger + } + } + ) { + s = Ganache.server(options); + return s.listen(port); + } + + async function teardown() { + // if the server is open or opening, try to close it. + if (s && s.status & Status.open) { + await s.close(); + } + } + + describe("http", () => { + async function simpleTest() { + const response = await request + .post("http://localhost:" + port) + .send(jsonRpcJson); + assert.strictEqual(response.status, 200); + + const json = JSON.parse(response.text); + assert.strictEqual(json.result, `${networkId}`); + return response; + } + + it("returns its status", async () => { + const s = Ganache.server(); + try { + assert.strictEqual(s.status, Status.closed); + const pendingListen = s.listen(port); + assert.strictEqual(s.status, Status.opening); + assert.ok( + s.status & Status.opening, + "Bitmask broken: can't be used to determine `open || closed` state" + ); + await pendingListen; + assert.strictEqual(s.status, Status.open); + assert.ok( + s.status & Status.open, + "Bitmask broken: can't be used to determine `open || closed` state" + ); + const pendingClose = s.close(); + assert.strictEqual(s.status, Status.closing); + assert.ok( + s.status & Status.closing, + "Bitmask broken: can't be used to determine `closed || closing` state" + ); + await pendingClose; + assert.strictEqual(s.status, Status.closed); + assert.ok( + s.status & Status.closed, + "Bitmask broken: can't be used to determine `closed || closing` state" + ); + } catch (e) { + // in case of failure, make sure we properly shut things down + if (s.status & Status.open) { + await s.close().catch(e => e); + } + throw e; + } + }); + + it("returns the net_version", async () => { + await setup(); + try { + await simpleTest(); + } finally { + await teardown(); + } + }); + + it("returns the net_version over a legacy-style connection listener", done => { + s = Ganache.server({ + chain: { networkId } + }); + s.listen(port, async () => { + try { + await simpleTest(); + } finally { + await teardown(); + } + done(); + }); + }); + + it("fails to `.listen()` twice, Promise", async () => { + await setup(); + try { + // the call to `setup()` above calls `listen()` already. if we call it + // again it should fail. + await assert.rejects(s.listen(port), { + message: `Server is already open on port: ${port}.` + }); + } finally { + await teardown(); + } + }); + + it("fails to `.listen()` twice, Callback", async () => { + await setup(); + try { + // the call to `setup()` above calls `listen()` already. if we call it + // again it should fail. + const listen = promisify(s.listen.bind(s)); + await assert.rejects(listen(port), { + message: `Server is already open on port: ${port}.` + }); + } finally { + await teardown(); + } + }); + + it("fails to `.close()` if server is closed", async () => { + await setup(); + try { + await s.close(); + assert.rejects(s.close(), { + message: "Server is already closed or closing." + }); + } finally { + await teardown(); + } + }); + + it("fails to `.close()` if server is closed", async () => { + await setup(); + try { + s.close(); + assert.rejects(s.close(), { + message: "Server is already closed or closing." + }); + } finally { + await teardown(); + } + }); + + it("fails to listen if the socket is already in use by 3rd party, Promise", async () => { + const server = http.createServer(); + server.listen(port); + + try { + await assert.rejects(setup, { + message: `listen EADDRINUSE: address already in use 127.0.0.1:${port}.` + }); + } finally { + await teardown(); + server.close(); + } + }); + + it("fails to listen if the socket is already in use by 3rd party, Callback", async () => { + const server = http.createServer(); + server.listen(port); + + try { + const s = Ganache.server(); + const listen = promisify(s.listen.bind(s)); + await assert.rejects(listen(port), { + message: `listen EADDRINUSE: address already in use 127.0.0.1:${port}.` + }); + } finally { + await teardown(); + server.close(); + } + }); + + // skip on Windows until https://github.com/uNetworking/uSockets/pull/101 is merged + (IS_WINDOWS ? xit : it)( + "fails to listen if the socket is already in use by Ganache", + async () => { + await setup(); + const s2 = Ganache.server(); + + try { + await assert.rejects(s2.listen(port), { + message: `listen EADDRINUSE: address already in use 127.0.0.1:${port}.` + }); + } catch (e) { + // in case of failure, make sure we properly shut things down + if (s2.status & Status.open) { + await s2.close().catch(e => e); + } + throw e; + } finally { + await teardown(); + } + } + ); + + it("rejects if listen called while server is closing, Promise", async () => { + await setup(); + try { + const closer = s.close(); + await assert.rejects(s.listen(4444), { + message: "Cannot start server while it is closing." + }); + await closer; + } finally { + await teardown(); + } + }); + + it("rejects if listen called while server is closing, Callback", async () => { + await setup(); + try { + const closer = s.close(); + const listen = promisify(s.listen.bind(s)); + await assert.rejects(listen(4444), { + message: "Cannot start server while it is closing." + }); + await closer; + } finally { + await teardown(); + } + }); + + it("rejects if close is called while opening", async () => { + const pendingSetup = setup(); + try { + await assert.rejects(s.close(), { + message: "Cannot close server while it is opening." + }); + } finally { + await pendingSetup; + await teardown(); + } + }); + + it("does not start a websocket server when `ws` is false", async () => { + await setup({ + server: { + ws: false + } + }); + try { + const ws = new WebSocket("ws://localhost:" + port); + + await assert.rejects( + new Promise((resolve, reject) => { + ws.on("open", resolve); + ws.on("error", reject); + }), + { + message: "Unexpected server response: 400" + } + ); + } finally { + await teardown(); + } + }); + + it("handles chunked requests (note: doesn't test `transfer-encoding: chunked`)", async () => { + await setup(); + try { + const req = request.post("http://localhost:" + port); + const json = JSON.stringify(jsonRpcJson); + + // we have to set the content-length because we can't use + // `Transfer-Encoding: chunked` with uWebSockets.js as of v15.9.0 + req.set("Content-Length", json.length.toString()); + + await new Promise((resolve, reject) => { + req.on("response", response => { + const json = JSON.parse(response.text); + assert.strictEqual(json.result, `${networkId}`); + resolve(void 0); + }); + req.on("error", () => { + reject(); + }); + + const readableStream = intoStream(json); + // make sure the data is sent as tiny pieces. + (readableStream as any)._readableState.highWaterMark = 8; + readableStream.pipe(req as any); + }); + } finally { + await teardown(); + } + }); + + it("returns 200/OK for RPC errors over HTTP", async () => { + await setup(); + const jsonRpcJson: any = { + jsonrpc: "2.0", + id: "1", + method: "eth_subscribe", + params: [] + }; + try { + const response = await request + .post("http://localhost:" + port) + .send(jsonRpcJson); + assert.strictEqual(response.status, 200); + assert.strictEqual( + JSON.parse(response.text).error.message, + "notifications not supported" + ); + } finally { + await teardown(); + } + }); + + it("handles batched json-rpc requests/responses", async () => { + await setup(); + const jsonRpcJson: any = [ + { + jsonrpc: "2.0", + id: "1", + method: "net_version", + params: [] + }, + { + jsonrpc: "2.0", + id: "2", + method: "eth_chainId", + params: [] + }, + { + jsonrpc: "2.0", + id: "3", + method: "eth_subscribe", // this one fails over HTTP + params: ["newHeads"] + } + ]; + try { + const response = await request + .post("http://localhost:" + port) + .send(jsonRpcJson); + const json = JSON.parse(response.text); + assert.deepStrictEqual(json[0], { + jsonrpc: "2.0", + id: "1", + result: "1234" + }); + assert.deepStrictEqual(json[1], { + jsonrpc: "2.0", + id: "2", + result: "0x539" + }); + assert.deepStrictEqual(json[2].jsonrpc, "2.0"); + assert.deepStrictEqual(json[2].id, "3"); + assert.deepStrictEqual(json[2].error.code, -32004); + assert.deepStrictEqual( + json[2].error.message, + "notifications not supported" + ); + } finally { + await teardown(); + } + }); + + it("returns a teapot (easter egg)", async () => { + await setup(); + try { + const result = await request + .get("http://localhost:" + port + "/418") + .catch(e => e); + assert.strictEqual(result.status, 418); + assert.strictEqual(result.message, "I'm a Teapot"); + } finally { + await teardown(); + } + }); + + it("returns 404 for bad routes", async () => { + await setup(); + const methods = [ + "get", + "post", + "head", + "options", + "put", + "delete", + "patch", + "trace" + ] as const; + try { + const requests = methods.map(async method => { + const result = await request[method]( + "http://localhost:" + port + "/there-is-no-spoon" + ).catch((e: any) => e); + assert.strictEqual(result.status, 404); + assert.strictEqual(result.message, "Not Found"); + }); + await Promise.all(requests); + } finally { + await teardown(); + } + }); + + it("doesn't crash when the request is aborted while waiting for repsonse", async () => { + await setup(); + + try { + const provider = s.provider; + const oldRequestRaw = (provider as any)._requestRaw; + const req = request.post("http://localhost:" + port); + const abortPromise = new Promise(resolve => { + (provider as any)._requestRaw = () => { + // abort the request object after intercepting the request + req.abort(); + return new Promise(innerResolve => { + // It takes 2 passes of the event loop to register the `abort` + // server-side: + setImmediate(setImmediate, () => { + // resolve the `provider.send` to make sure the server can + // handle _not_ responding to a request that has been aborted: + innerResolve({ value: Promise.resolve() as any }); + // and finally, resolve the `abort` promise: + resolve(void 0); + }); + }); + }; + }); + const result = await req.send(jsonRpcJson).catch(e => e); + assert.strictEqual(result.code, "ABORTED", "Response was not aborted"); + + // wait for the server to react to the requesrt's `abort` + await abortPromise; + + provider._requestRaw = oldRequestRaw; + + // now make sure we are still up and running: + await simpleTest(); + } finally { + await teardown(); + } + }); + + it("server closes when told to", async () => { + await setup(); + + try { + await s.close(); + const req = request.post("http://localhost:" + port); + await assert.rejects(req.send(jsonRpcJson), { + code: "ECONNREFUSED" + }); + } finally { + await teardown(); + } + }); + + describe("CORS", () => { + const optionsHeaders = [ + "Access-Control-Allow-Methods", + "Access-Control-Allow-Headers", + "Access-Control-Max-Age" + ] as const; + const baseHeaders = [ + "Access-Control-Allow-Credentials", + "Access-Control-Allow-Origin" + ] as const; + const allCorsHeaders = [...optionsHeaders, ...baseHeaders] as const; + + it("does not return CORS headers for non-CORS requests", async () => { + await setup(); + try { + const resp = await simpleTest(); + allCorsHeaders.forEach(header => { + assert.strictEqual( + resp.header[header.toLowerCase()], + void 0, + `Non-CORS response should not contain header ${header}` + ); + }); + } finally { + await teardown(); + } + }); + + it("returns only base CORS headers for post request with origin header", async () => { + await setup(); + const origin = "origin"; + try { + const resp = await request + .post("http://localhost:" + port) + .set("origin", origin) + .send(jsonRpcJson); + assert.strictEqual(resp.status, 200); + assert.strictEqual( + resp.header["access-control-allow-credentials"], + "true" + ); + assert.strictEqual( + resp.header["access-control-allow-origin"], + origin + ); + optionsHeaders.forEach(header => { + assert.strictEqual( + resp.header[header.toLowerCase()], + void 0, + `Non-CORS response should not contain header ${header}` + ); + }); + } finally { + await teardown(); + } + }); + + it("returns all CORS headers for request options request with origin header", async () => { + await setup(); + const origin = "origin"; + try { + const resp = await request + .options("http://localhost:" + port) + .set("origin", origin) + .send(jsonRpcJson); + assert.strictEqual(resp.status, 204); + assert.strictEqual( + resp.header["access-control-allow-methods"], + "POST" + ); + assert.strictEqual( + resp.header["access-control-allow-origin"], + origin + ); + assert.strictEqual(resp.header["access-control-max-age"], "600"); + assert.strictEqual(resp.header["content-length"], "0"); + assert.strictEqual( + resp.header["access-control-allow-credentials"], + "true" + ); + } finally { + await teardown(); + } + }); + + it("echos Access-Control-Request-Headers for options request", async () => { + await setup(); + const origin = "origin"; + const acrh = "origin, content-length, x-random"; + try { + const resp = await request + .options("http://localhost:" + port) + .set("origin", origin) + .set("Access-Control-Request-Headers", acrh) + .send(jsonRpcJson); + + assert.strictEqual(resp.status, 204); + assert.strictEqual(resp.header["access-control-allow-headers"], acrh); + } finally { + await teardown(); + } + }); + }); + }); + + describe("websocket", () => { + beforeEach(setup); + afterEach(teardown); + + it("returns the net_version over a websocket", async () => { + const ws = new WebSocket("ws://localhost:" + port); + + const response: any = await new Promise(resolve => { + ws.on("open", () => { + ws.send(JSON.stringify(jsonRpcJson)); + }); + ws.on("message", resolve); + }); + const json = JSON.parse(response); + assert.strictEqual(json.result, `${networkId}`); + }); + + it("returns the net_version over a websocket as binary", async () => { + const ws = new WebSocket("ws://localhost:" + port); + const response: any = await new Promise(resolve => { + ws.on("open", () => { + const strToAB = (str: string) => + new Uint8Array(str.split("").map(c => c.charCodeAt(0))).buffer; + ws.send(strToAB(JSON.stringify(jsonRpcJson))); + }); + ws.on("message", resolve); + }); + assert.strictEqual( + response.constructor, + Buffer, + "response doesn't seem to be a Buffer as expect" + ); + const json = JSON.parse(response); + assert.strictEqual( + json.result, + `${networkId}`, + "Binary data result is not as expected" + ); + }); + + it("doesn't crash when sending bad data over http", async () => { + await assert.rejects( + request.post("http://localhost:" + port).send("This is _not_ pudding."), + { + message: "Bad Request" + } + ); + + const response = await request + .post("http://localhost:" + port) + .send(jsonRpcJson); + const json = JSON.parse(response.text); + assert.strictEqual(json.result, `${networkId}`); + }); + + it("doesn't crash when sending bad data over websocket", async () => { + const ws = new WebSocket("ws://localhost:" + port); + const result = await new Promise(resolve => { + ws.on("open", () => { + ws.on("message", resolve); + ws.send("What is it?"); + }); + }); + const json = JSON.parse(result); + assert.strictEqual(json.error.code, -32700); + }); + + it("doesn't crash when the connection is closed while a request is in flight", async () => { + const provider = s.provider; + provider._requestRaw = (async () => { + // close our websocket after intercepting the request + await s.close(); + return { value: Promise.resolve(void 0) }; + }) as any; + + const ws = new WebSocket("ws://localhost:" + port); + return new Promise((resolve, reject) => { + ws.on("open", () => { + // If we get a message that means things didn't get closed as they + // should have OR they are closing too late for some reason and + // this test isn't testing anything. + ws.on("message", () => + reject("Got a message when we shouldn't have!") + ); + + // make sure we leave enough time for things to crash if it does end + // up crashing. + ws.on("close", () => setImmediate(resolve)); + + // The RPC request method doesn't matter since we're duck punching our + // provider.send method anyway. + ws.send(JSON.stringify(jsonRpcJson)); + }); + }); + }); + + it("handles PromiEvent messages", async () => { + const provider = s.provider; + const message = "I hope you get this message"; + const oldRequestRaw = provider._requestRaw.bind(provider); + provider._requestRaw = (async () => { + const promiEvent = new PromiEvent(resolve => { + const subId = "0xsubscriptionId"; + resolve(subId); + setImmediate(() => + promiEvent.emit("message", { + data: { subscription: subId, result: message } + }) + ); + }); + return { value: promiEvent }; + }) as any; + + const ws = new WebSocket("ws://localhost:" + port); + const result = await new Promise(resolve => { + ws.on("open", () => { + ws.on("message", data => { + const { result, params } = JSON.parse(data.toString()); + // ignore the initial response + if (result === "0xsubscriptionId") return; + + resolve(params.result); + }); + + const subscribeJson: any = { + jsonrpc: "2.0", + id: "1", + method: "eth_subscribe", + params: [] + }; + ws.send(JSON.stringify(subscribeJson)); + }); + }); + + assert.strictEqual(result, message); + + provider._requestRaw = oldRequestRaw; + }); + + it("handles batched json-rpc requests/responses", async () => { + const jsonRpcJson: any = [ + { + jsonrpc: "2.0", + id: "1", + method: "net_version", + params: [] + }, + { + jsonrpc: "2.0", + id: "2", + method: "eth_chainId", + params: [] + }, + { + jsonrpc: "2.0", + id: "3", + method: "eth_subscribe", // this one works here in WS-land + params: ["newHeads"] + } + ]; + + const ws = new WebSocket("ws://localhost:" + port); + const response: any = await new Promise(resolve => { + ws.on("open", () => { + ws.send(JSON.stringify(jsonRpcJson)); + }); + ws.on("message", resolve); + }); + ws.close(); + + const json = JSON.parse(response); + assert.deepStrictEqual(json, [ + { + jsonrpc: "2.0", + id: "1", + result: "1234" + }, + { + jsonrpc: "2.0", + id: "2", + result: "0x539" + }, + { + jsonrpc: "2.0", + id: "3", + result: "0x1" + } + ]); + }); + + it("handles invalid json-rpc JSON", async () => { + const ws = new WebSocket("ws://localhost:" + port); + const response = await new Promise(resolve => { + ws.on("open", () => { + ws.send(JSON.stringify(null)); + }); + ws.on("message", data => { + resolve(JSON.parse(data.toString())); + }); + }); + assert.strictEqual(response.error.code, -32700); + }); + + it("doesn't crash when the connection is closed while a subscription is in flight", async () => { + const provider = s.provider; + let promiEvent: PromiEvent; + provider._requestRaw = (async () => { + promiEvent = new PromiEvent(resolve => { + resolve("0xsubscriptionId"); + }); + return { value: promiEvent }; + }) as any; + + const ws = new WebSocket("ws://localhost:" + port); + return new Promise((resolve, reject) => { + ws.on("open", () => { + // If we get a message that means things didn't get closed as they + // should have OR they are closing too late for some reason and + // this test isn't testing anything. + ws.on("message", data => { + if (JSON.parse(data.toString()).result === "0xsubscriptionId") { + // close our websocket after intercepting the request + s.close(); + // then attempt to send a message back right after closing: + promiEvent.emit("message", "I hope you don't get this message"); + return; + } + // the above message should never be received + reject("Got a subscription message when we shouldn't have!"); + }); + + // make sure we leave enough time for things to crash if it does end + // up crashing. + ws.on("close", () => setImmediate(resolve)); + + const subscribeJson: any = { + jsonrpc: "2.0", + id: "1", + method: "eth_subscribe", + params: [] + }; + ws.send(JSON.stringify(subscribeJson)); + }); + }); + }); + + // TODO: actually handle backpressure! + it.skip("can handle backpressure", async () => { + { + // create tons of data to force websocket backpressure + const huge = {}; + for (let i = 0; i < 1e6; i++) huge["prop_" + i] = { i }; + s.provider._requestRaw = (async () => { + return { value: Promise.resolve(huge) }; + }) as any; + } + + const ws = new WebSocket("ws://localhost:" + port); + const oldLog = logger.log; + try { + let gotBackpressure = false; + // duck punch `logger.log` so we can intercept logs + logger.log = (message: string) => { + if (message.indexOf("WebSocket backpressure: ") === 0) { + gotBackpressure = true; + } + }; + return await new Promise((resolve, reject) => { + ws.on("open", () => { + ws.on("message", _message => { + if (gotBackpressure) { + resolve(); + } else { + reject( + new Error( + "Possible false positive: Didn't detect backpressure" + + " before receiving a message. Ensure `s.provider.send` is" + + " sending enough data." + ) + ); + } + }); + + // The RPC request method doesn't matter since we're duck punching + // our provider.send method anyway. + ws.send(JSON.stringify(jsonRpcJson)); + }); + }); + } finally { + // put the original logger back so other tests that might rely on it + // don't break. + logger.log = oldLog; + } + }).timeout(10000); + }); +}); diff --git a/src/packages/core/tests/testdb/!trie_db!0x08ac839d755e4a25bcbc47a4012219db100ef0a340307869393f9df55ebd470c b/src/packages/core/tests/testdb/!trie_db!0x08ac839d755e4a25bcbc47a4012219db100ef0a340307869393f9df55ebd470c new file mode 100644 index 0000000000..a64fa743b7 --- /dev/null +++ b/src/packages/core/tests/testdb/!trie_db!0x08ac839d755e4a25bcbc47a4012219db100ef0a340307869393f9df55ebd470c @@ -0,0 +1 @@ +"0xf871a06990c157721aea0e000dc63d12ccdd1938364fb8e72dcdda25d6baa70992b80f808080808080808080808080a07559bb4901892880aec39ee574a87e32492071f22d0a42e184892f6b225df9b380a0de941f06d6f99270e651ece36725c555afc7fdfc4855bd86add2cdcdec4a4de380" \ No newline at end of file diff --git a/src/packages/core/tests/testdb/!trie_db!0x6990c157721aea0e000dc63d12ccdd1938364fb8e72dcdda25d6baa70992b80f b/src/packages/core/tests/testdb/!trie_db!0x6990c157721aea0e000dc63d12ccdd1938364fb8e72dcdda25d6baa70992b80f new file mode 100644 index 0000000000..6ff361512c --- /dev/null +++ b/src/packages/core/tests/testdb/!trie_db!0x6990c157721aea0e000dc63d12ccdd1938364fb8e72dcdda25d6baa70992b80f @@ -0,0 +1 @@ +"0xf59310000000000000000000000000000000000000a0b0108c95b74533d6862f59a730bb0282bbaaadd8ac1b94510b69a499527c3505" \ No newline at end of file diff --git a/src/packages/core/tests/testdb/!trie_db!0xb0108c95b74533d6862f59a730bb0282bbaaadd8ac1b94510b69a499527c3505 b/src/packages/core/tests/testdb/!trie_db!0xb0108c95b74533d6862f59a730bb0282bbaaadd8ac1b94510b69a499527c3505 new file mode 100644 index 0000000000..6a23c9999a --- /dev/null +++ b/src/packages/core/tests/testdb/!trie_db!0xb0108c95b74533d6862f59a730bb0282bbaaadd8ac1b94510b69a499527c3505 @@ -0,0 +1 @@ +"0xf90131a0304356a9ff9f36e260c1ef38658725d9067d9e85450d043946d439cae014547ba05911f24d96912350de50f297c2d34d5d10e136757bf4cfff5fa41bfca219554aa05911f24d96912350de50f297c2d34d5d10e136757bf4cfff5fa41bfca219554aa05911f24d96912350de50f297c2d34d5d10e136757bf4cfff5fa41bfca219554aa05911f24d96912350de50f297c2d34d5d10e136757bf4cfff5fa41bfca219554aa05911f24d96912350de50f297c2d34d5d10e136757bf4cfff5fa41bfca219554aa05911f24d96912350de50f297c2d34d5d10e136757bf4cfff5fa41bfca219554aa05911f24d96912350de50f297c2d34d5d10e136757bf4cfff5fa41bfca219554aa05911f24d96912350de50f297c2d34d5d10e136757bf4cfff5fa41bfca219554a8080808080808080" \ No newline at end of file diff --git a/src/packages/core/tests/testdb/!trie_db!0xf173aa08e820d7e4b4bb0c243a1661770198770b14029eed74f0eb473c79cd83 b/src/packages/core/tests/testdb/!trie_db!0xf173aa08e820d7e4b4bb0c243a1661770198770b14029eed74f0eb473c79cd83 new file mode 100644 index 0000000000..3472769b46 --- /dev/null +++ b/src/packages/core/tests/testdb/!trie_db!0xf173aa08e820d7e4b4bb0c243a1661770198770b14029eed74f0eb473c79cd83 @@ -0,0 +1 @@ +"0xf8f1a008ac839d755e4a25bcbc47a4012219db100ef0a340307869393f9df55ebd470c80a0fa71baff75cc869d687859edac6345402a902e385a2829b9bded7697113e98368080a0a692717e52ff2d01d314834d9a639e60fad01fac4634d78c7203c6916e3f17fca03781707048c5d3acf2d0a78e1c8990e0f19a3fe5909007a6aefe8a9b0402689980a0a9c678e4e10500df2d3c913e87ce2f1b38b12409f5c65078b201783d6280e764808080a069b7a8125fdd1dac0b872648905e0e1410b8859b9fdfc1991e3860eecbcaa2da8080a003a0f12083f4cdb767e0f47613296e562cafa8a25a91deb88a47433ccc4e138e80" \ No newline at end of file diff --git a/src/packages/core/tsconfig.json b/src/packages/core/tsconfig.json new file mode 100644 index 0000000000..25d5c3cf7e --- /dev/null +++ b/src/packages/core/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts"] +} diff --git a/src/packages/flavors/.npmignore b/src/packages/flavors/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/packages/flavors/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/packages/flavors/LICENSE b/src/packages/flavors/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/packages/flavors/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/packages/flavors/README.md b/src/packages/flavors/README.md new file mode 100644 index 0000000000..e1b8783f7e --- /dev/null +++ b/src/packages/flavors/README.md @@ -0,0 +1,3 @@ +# `@ganache/flavors` + +Ganache's flavors enumeration and TypeScript types diff --git a/src/packages/flavors/index.ts b/src/packages/flavors/index.ts new file mode 100644 index 0000000000..49fe84df43 --- /dev/null +++ b/src/packages/flavors/index.ts @@ -0,0 +1,25 @@ +// import {TezosConnector} from "@ganache/tezos"; +import * as Ethereum from "@ganache/ethereum"; + +export const DefaultFlavor = Ethereum.FlavorName; + +export type ConnectorsByName = { + [Ethereum.FlavorName]: Ethereum.Connector; + // [Tezos.FlavorName]: Tezos.Connector +}; + +export const ConnectorsByName = { + [Ethereum.FlavorName]: Ethereum.Connector + // [Tezos.FlavorName]: Tezos.Connector +}; + +export type Connectors = { + [K in keyof ConnectorsByName]: ConnectorsByName[K]; +}[keyof ConnectorsByName]; + +export type Providers = Ethereum.Provider /*| Tezos.Provider */; + +export type Options = { + flavor?: typeof Ethereum.FlavorName; +} & Ethereum.ProviderOptions; +// | [Tezos.FlavorName]: Tezos.ProviderOptions; diff --git a/src/packages/flavors/npm-shrinkwrap.json b/src/packages/flavors/npm-shrinkwrap.json new file mode 100644 index 0000000000..2fc171fdb6 --- /dev/null +++ b/src/packages/flavors/npm-shrinkwrap.json @@ -0,0 +1,245 @@ +{ + "name": "@ganache/flavors", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "google-closure-compiler": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20201102.0.1.tgz", + "integrity": "sha512-Cz+1jOswH0MwMVPu1rRH1xD4KYuY5XW2ox5aXwqaAxevqmirhr36f8wgKPHuVRSovFejW640r6UFwyrOT6U0CA==", + "dev": true, + "requires": { + "chalk": "2.x", + "google-closure-compiler-java": "^20201102.0.1", + "google-closure-compiler-linux": "^20201102.0.1", + "google-closure-compiler-osx": "^20201102.0.1", + "google-closure-compiler-windows": "^20201102.0.1", + "minimist": "1.x", + "vinyl": "2.x", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "google-closure-compiler-java": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20201102.0.1.tgz", + "integrity": "sha512-pXJIlyqepHhih0HCbShkAZJyViIxdyd4V7MnCUZEXLIIlygw92e2dC+5XiONDQZgRlF93BPmWCy9jr7wYoW1hQ==", + "dev": true + }, + "google-closure-compiler-linux": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20201102.0.1.tgz", + "integrity": "sha512-aRbyTGnQoFXchcpEFNrP1p/WIvYOgN3hYKI+MOHWkvwVJBY2P8gpb07hAigO8fj+QKD/SFCl+2pXP+JniWOEqw==", + "dev": true, + "optional": true + }, + "google-closure-compiler-osx": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20201102.0.1.tgz", + "integrity": "sha512-VguqEAOYI6XYZN6JcLMP8fpsoXk1Z9YuntMjv0IDVydkbZaHYOI4zE39FJhMuWiN7gOzSX2b/BBC6GsSh1F3fw==", + "dev": true, + "optional": true + }, + "google-closure-compiler-windows": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20201102.0.1.tgz", + "integrity": "sha512-LlynipQi/iP76mjkOu6Rc1mCRuxTAhRvLjq10aGfVjKwpbCAF0Jq2a5k2ygr4xYiINNi2/L2qUw6ObPm9wQCOw==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + } + } +} diff --git a/src/packages/flavors/package.json b/src/packages/flavors/package.json new file mode 100644 index 0000000000..060097bda8 --- /dev/null +++ b/src/packages/flavors/package.json @@ -0,0 +1,51 @@ +{ + "name": "@ganache/flavors", + "version": "0.1.0", + "description": "Ganache's flavors enumeration and TypeScript types", + "author": "David Murdoch (https://davidmurdoch.com)", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/packages/flavors#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "source": "index.ts", + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "lib" + ], + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/packages/flavors" + }, + "scripts": { + "tsc": "ttsc" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ganache-flavors", + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling" + ], + "dependencies": { + "@ganache/ethereum": "^0.1.0", + "@ganache/tezos": "^0.1.0", + "@ganache/utils": "^0.1.0" + }, + "devDependencies": { + "google-closure-compiler": "20201102.0.1" + } +} diff --git a/src/packages/flavors/tests/index.test.ts b/src/packages/flavors/tests/index.test.ts new file mode 100644 index 0000000000..81945f1965 --- /dev/null +++ b/src/packages/flavors/tests/index.test.ts @@ -0,0 +1,5 @@ +import assert from "assert"; + +describe("@ganache/flavors", () => { + it("needs tests"); +}); diff --git a/src/packages/flavors/tsconfig.json b/src/packages/flavors/tsconfig.json new file mode 100644 index 0000000000..25d5c3cf7e --- /dev/null +++ b/src/packages/flavors/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts"] +} diff --git a/src/packages/ganache/.npmignore b/src/packages/ganache/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/packages/ganache/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/packages/ganache/LICENSE b/src/packages/ganache/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/packages/ganache/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/packages/ganache/README.md b/src/packages/ganache/README.md new file mode 100644 index 0000000000..8c29560519 --- /dev/null +++ b/src/packages/ganache/README.md @@ -0,0 +1,3 @@ +# `ganache` + +> TODO: description diff --git a/src/packages/ganache/index.ts b/src/packages/ganache/index.ts new file mode 100644 index 0000000000..edc13ead4d --- /dev/null +++ b/src/packages/ganache/index.ts @@ -0,0 +1,6 @@ +import Ganache from "@ganache/cli"; + +export default { + server: Ganache.server, + provider: Ganache.provider +}; diff --git a/src/packages/ganache/npm-shrinkwrap.json b/src/packages/ganache/npm-shrinkwrap.json new file mode 100644 index 0000000000..51019d29c1 --- /dev/null +++ b/src/packages/ganache/npm-shrinkwrap.json @@ -0,0 +1,2362 @@ +{ + "name": "ganache", + "version": "3.0.0-internal.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/eslint": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.4.tgz", + "integrity": "sha512-YCY4kzHMsHoyKspQH+nwSe+70Kep7Vjt2X+dZe5Vs2vkRudqtoFoUIv1RlJmZB8Hbp7McneupoZij4PadxsK5Q==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", + "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.45", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz", + "integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, + "@types/node": { + "version": "14.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz", + "integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/info": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.1.0.tgz", + "integrity": "sha512-uNWSdaYHc+f3LdIZNwhdhkjjLDDl3jP2+XBqAq9H8DjrJUvlOKdP8TNruy1yEaDfgpAIgbSAN7pye4FEHg9tYQ==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.1.0.tgz", + "integrity": "sha512-7RfnMXCpJ/NThrhq4gYQYILB18xWyoQcBey81oIyVbmgbc6m5ZHHyFK+DyH7pLHJf0p14MxL4mTsoPAgBSTpIg==", + "dev": true + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "requires": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, + "acorn": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.4.tgz", + "integrity": "sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", + "dev": true + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "dev": true, + "requires": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "requires": { + "bindings": "^1.3.0" + } + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "browserslist": { + "version": "4.14.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.6.tgz", + "integrity": "sha512-zeFYcUo85ENhc/zxHbiIp0LGzzTrE2Pv2JhxvS7kpUb9Q9D38kUX6Bie7pGutJ/5iF5rOxE7CepAuWD56xJ33A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001154", + "electron-to-chromium": "^1.3.585", + "escalade": "^3.1.1", + "node-releases": "^1.1.65" + } + }, + "buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz", + "integrity": "sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001154", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001154.tgz", + "integrity": "sha512-y9DvdSti8NnYB9Be92ddMZQrcOe04kcQtcxtBx4NkB04+qZ+JUWotnXBJTmxlKudhxNTQ3RRknMwNU2YQl/Org==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, + "command-line-usage": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", + "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "chalk": "^2.4.2", + "table-layout": "^1.0.0", + "typical": "^5.2.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "electron-to-chromium": { + "version": "1.3.588", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.588.tgz", + "integrity": "sha512-0zr+ZfytnLeJZxGgmEpPTcItu5Mm4A5zHPZXLfHcGp0mdsk95rmD7ePNewYtK1yIdLbk8Z1U2oTRRfOtR4gbYg==", + "dev": true + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.3.1.tgz", + "integrity": "sha512-G1XD3MRGrGfNcf6Hg0LVZG7GIKcYkbfHa5QMxt1HDUTdYoXH0JR1xXyg+MaKLF73E9A27uWNVxvFivNRYeUB6w==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.0.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "envinfo": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.3.tgz", + "integrity": "sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "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": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==" + }, + "import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-core-module": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", + "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true + }, + "is-nan": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz", + "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typed-array": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz", + "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.0", + "es-abstract": "^1.17.4", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "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-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" + } + } + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" + } + } + }, + "level-concat-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", + "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==" + }, + "level-js": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/level-js/-/level-js-5.0.2.tgz", + "integrity": "sha512-SnBIDo2pdO5VXh02ZmtAyPP6/+6YTJg2ibLtl9C34pWvmtMEmRTWpra+qO/hifkUtBTOtfx6S9vLDjBsBK4gRg==", + "dev": true, + "requires": { + "abstract-leveldown": "~6.2.3", + "buffer": "^5.5.0", + "inherits": "^2.0.3", + "ltgt": "^2.1.2" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, + "level-supports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", + "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", + "requires": { + "xtend": "^4.0.2" + } + }, + "leveldown": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-5.6.0.tgz", + "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", + "requires": { + "abstract-leveldown": "~6.2.1", + "napi-macros": "~2.0.0", + "node-gyp-build": "~4.1.0" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "loader-runner": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.1.0.tgz", + "integrity": "sha512-oR4lB4WvwFoC70ocraKhn5nkKSs23t57h9udUgw8o0iH8hMXeEoRuUgfcvgUwAJ1ZpRqBvcou4N2SMvM1DwMrA==", + "dev": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", + "dev": true + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "napi-macros": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", + "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node-gyp-build": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", + "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==" + }, + "node-loader": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/node-loader/-/node-loader-1.0.2.tgz", + "integrity": "sha512-myxAxpyMR7knjA4Uzwf3gjxaMtxSWj2vpm9o6AYWWxQ1S3XMBNeG2vzYcp/5eW03cBGfgSxyP+wntP8qhBJNhQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "node-releases": { + "version": "1.1.65", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.65.tgz", + "integrity": "sha512-YpzJOe2WFIW0V4ZkJQd/DGR/zdVwc/pI4Nl1CZrBO19FdRcSTmsuhdttw9rsTzzJLrNcSloLiBbEYx1C4f6gpA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-is": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", + "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "dev": true + }, + "resolve": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", + "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", + "dev": true, + "requires": { + "is-core-module": "^2.0.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-loader": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shebang-loader/-/shebang-loader-0.0.1.tgz", + "integrity": "sha1-pAAEldRMzu++xjQ157FphWn6Uuw=", + "dev": true + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "table-layout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.1.tgz", + "integrity": "sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + } + }, + "tapable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.0.0.tgz", + "integrity": "sha512-bjzn0C0RWoffnNdTzNi7rNDhs1Zlwk2tRXgk8EiHKAOX1Mag3d6T0Y5zNa7l9CJ+EoUne/0UHdwS8tMbkh9zDg==", + "dev": true + }, + "terser": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.8.tgz", + "integrity": "sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.0.3.tgz", + "integrity": "sha512-zFdGk8Lh9ZJGPxxPE6jwysOlATWB8GMW8HcfGULWA/nPal+3VdATflQvSBSLQJRCmYZnfFJl6vkRTiwJGNgPiQ==", + "dev": true, + "requires": { + "jest-worker": "^26.6.1", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.8" + }, + "dependencies": { + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-loader": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.0.7.tgz", + "integrity": "sha512-ooa4wxlZ9TOXaJ/iVyZlWsim79Ul4KyifSwyT2hOrbQA6NZJypsLOE198o8Ko+JV+ZHnMArvWcl4AnRqpCU/Mw==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + } + } + }, + "ts-node": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "ttypescript": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/ttypescript/-/ttypescript-1.5.12.tgz", + "integrity": "sha512-1ojRyJvpnmgN9kIHmUnQPlEV1gq+VVsxVYjk/NfvMlHSmYxjK5hEvOOU2MQASrbekTUiUM7pR/nXeCc8bzvMOQ==", + "dev": true, + "requires": { + "resolve": ">=1.9.0" + } + }, + "typescript": { + "version": "4.1.1-rc", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.1-rc.tgz", + "integrity": "sha512-tgNcFrLIjlaMWEc7bKC0bxLNIt8BIAauY/HLUOQDyTP75HGskETtXOt46x4EKAHRKhWVLMc7yM02puTHa/yhCA==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", + "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "watchpack": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.0.1.tgz", + "integrity": "sha512-vO8AKGX22ZRo6PiOFM9dC0re8IcKh8Kd/aH2zeqUc6w4/jBGlTy2P7fTC6ekT0NjVeGjgU2dGC5rNstKkeLEQg==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webpack": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.4.0.tgz", + "integrity": "sha512-udpYTyqz8toTTdaOsL2QKPLeZLt2IEm9qY7yTXuFEQhKu5bk0yQD9BtAdVQksmz4jFbbWOiWmm3NHarO0zr/ng==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.45", + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^8.0.4", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.3.1", + "eslint-scope": "^5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.1.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "pkg-dir": "^4.2.0", + "schema-utils": "^3.0.0", + "tapable": "^2.0.0", + "terser-webpack-plugin": "^5.0.3", + "watchpack": "^2.0.0", + "webpack-sources": "^2.1.1" + } + }, + "webpack-cli": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.2.0.tgz", + "integrity": "sha512-EIl3k88vaF4fSxWSgtAQR+VwicfLMTZ9amQtqS4o+TDPW9HGaEpbFBbAZ4A3ZOT5SOnMxNOzROsSTPiE8tBJPA==", + "dev": true, + "requires": { + "@webpack-cli/info": "^1.1.0", + "@webpack-cli/serve": "^1.1.0", + "colorette": "^1.2.1", + "command-line-usage": "^6.1.0", + "commander": "^6.2.0", + "enquirer": "^2.3.6", + "execa": "^4.1.0", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "leven": "^3.1.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^4.2.2" + }, + "dependencies": { + "commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "webpack-sources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", + "dev": true, + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-typed-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz", + "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "es-abstract": "^1.17.5", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "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-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" + } + } + } + }, + "wordwrapjs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz", + "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==", + "dev": true, + "requires": { + "reduce-flatten": "^2.0.0", + "typical": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + } + } +} diff --git a/src/packages/ganache/package.json b/src/packages/ganache/package.json new file mode 100644 index 0000000000..06ce1ecce1 --- /dev/null +++ b/src/packages/ganache/package.json @@ -0,0 +1,80 @@ +{ + "name": "ganache", + "version": "3.0.0-internal.0", + "description": "A library and cli to create a local blockchain for fast Ethereum development.", + "author": "David Murdoch", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/packages/ganache#readme", + "license": "MIT", + "main": "dist/node/ganache.min.js", + "browser": "dist/web/ganache.min.js", + "types": "lib/index.d.ts", + "source": "index.ts", + "bin": { + "ganache": "dist/cli/ganache.min.js", + "ganache-cli": "dist/cli/ganache.min.js" + }, + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/packages/ganache" + }, + "scripts": { + "build": "webpack", + "tsc": "ttsc", + "test": "nyc npm run mocha", + "mocha": "cross-env TS_NODE_COMPILER=ttypescript TS_NODE_FILES=true mocha --exit --check-leaks --throw-deprecation --trace-warnings --require ts-node/register 'tests/**/*.test.ts'" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling", + "truffle" + ], + "devDependencies": { + "@ganache/cli": "^0.1.0", + "@ganache/flavors": "^0.1.0", + "@types/node": "14.14.6", + "assert": "2.0.0", + "buffer": "6.0.1", + "crypto-browserify": "3.12.0", + "events": "3.2.0", + "level-js": "5.0.2", + "node-loader": "1.0.2", + "os-browserify": "0.3.0", + "path-browserify": "1.0.1", + "process": "0.11.10", + "shebang-loader": "0.0.1", + "stream-browserify": "3.0.0", + "ts-loader": "8.0.7", + "ts-node": "9.0.0", + "ttypescript": "1.5.12", + "typescript": "4.1.1-rc", + "util": "0.12.3", + "webpack": "5.4.0", + "webpack-cli": "4.2.0" + }, + "dependencies": { + "bigint-buffer": "1.1.5", + "keccak": "3.0.1", + "leveldown": "5.6.0", + "secp256k1": "4.0.2" + } +} diff --git a/src/packages/ganache/src/cli.ts b/src/packages/ganache/src/cli.ts new file mode 100644 index 0000000000..138f2163f5 --- /dev/null +++ b/src/packages/ganache/src/cli.ts @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +import "@ganache/cli/cli"; diff --git a/src/packages/ganache/tests/index.test.ts b/src/packages/ganache/tests/index.test.ts new file mode 100644 index 0000000000..70ad885d99 --- /dev/null +++ b/src/packages/ganache/tests/index.test.ts @@ -0,0 +1,6 @@ +import assert from "assert"; +import ganache from ".."; + +describe("@ganache/ganache", () => { + it("needs tests"); +}); diff --git a/src/packages/ganache/tsconfig.json b/src/packages/ganache/tsconfig.json new file mode 100644 index 0000000000..2bb885156a --- /dev/null +++ b/src/packages/ganache/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts", "src/cli.ts"] +} diff --git a/src/packages/ganache/webpack.config.ts b/src/packages/ganache/webpack.config.ts new file mode 100644 index 0000000000..a6ce6ef258 --- /dev/null +++ b/src/packages/ganache/webpack.config.ts @@ -0,0 +1,5 @@ +import webpackBrowser from "./webpack/webpack.browser.config"; +import webpackNode from "./webpack/webpack.node.config"; +import webpackCli from "./webpack/webpack.cli.config"; + +export default [webpackBrowser, webpackNode, webpackCli]; diff --git a/src/packages/ganache/webpack/polyfills/browser-bigint-buffer.ts b/src/packages/ganache/webpack/polyfills/browser-bigint-buffer.ts new file mode 100644 index 0000000000..8df9d9f3a0 --- /dev/null +++ b/src/packages/ganache/webpack/polyfills/browser-bigint-buffer.ts @@ -0,0 +1,4 @@ +export function toBigIntBE(buf: Buffer) { + // TODO(perf): this is slow. Can we make it fast in browserland? + return BigInt(`0x${buf.toString("hex")}`); +} diff --git a/src/packages/ganache/webpack/polyfills/browser-tmp-promise.ts b/src/packages/ganache/webpack/polyfills/browser-tmp-promise.ts new file mode 100644 index 0000000000..5e35d343b0 --- /dev/null +++ b/src/packages/ganache/webpack/polyfills/browser-tmp-promise.ts @@ -0,0 +1,364 @@ +declare const indexedDB: any; + +import { resolve, isAbsolute, basename, join, relative } from "path"; +import { randomBytes, pseudoRandomBytes } from "crypto"; + +export interface TmpNameOptions { + dir?: string; + name?: string; + postfix?: string; + prefix?: string; + template?: string; + tmpdir?: string; + tries?: number; +} + +export interface DirOptions extends TmpNameOptions { + keep?: boolean; + mode?: number; + unsafeCleanup?: boolean; +} + +const // the random characters to choose from + RANDOM_CHARS = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + TEMPLATE_PATTERN = /XXXXXX/, + DEFAULT_TRIES = 3, + _removeObjects = []; + +let _gracefulCleanup = false; + +/** + * The garbage collector. + * + * @private + */ +async function _garbageCollector() { + /* istanbul ignore else */ + if (!_gracefulCleanup) return; + + // the function being called removes itself from _removeObjects, + // loop until _removeObjects is empty + while (_removeObjects.length) { + try { + _removeObjects[0](); + } catch (e) { + // already removed? + } + } +} + +/** + * Random name generator based on crypto. + * Adapted from http://blog.tompawlak.org/how-to-generate-random-values-nodejs-javascript + * + * @param {number} howMany + * @returns {string} the generated random name + * @private + */ +function _randomChars(howMany: number) { + let value = [], + rnd = null; + + // make sure that we do not fail because we ran out of entropy + try { + rnd = randomBytes(howMany); + } catch (e) { + rnd = pseudoRandomBytes(howMany); + } + + for (var i = 0; i < howMany; i++) { + value.push(RANDOM_CHARS[rnd[i] % RANDOM_CHARS.length]); + } + + return value.join(""); +} + +/** + * Helper which determines whether a string s is blank, that is undefined, or empty or null. + * + * @private + * @param {string} s + * @returns {Boolean} true whether the string s is blank, false otherwise + */ +function _isBlank(s: string) { + return s === null || _isUndefined(s) || !s.trim(); +} + +/** + * Checks whether the `obj` parameter is defined or not. + * + * @param {Object} obj + * @returns {boolean} true if the object is undefined + * @private + */ +function _isUndefined(obj: Object) { + return typeof obj === "undefined"; +} + +/** + * Generates a new temporary name. + * + * @param {Object} opts + * @returns {string} the new random name according to opts + * @private + */ +function _generateTmpName(options: TmpNameOptions) { + const tmpDir = options.tmpdir; + + /* istanbul ignore else */ + if (!_isUndefined(options.name)) + return join(tmpDir, options.dir, options.name); + + /* istanbul ignore else */ + if (!_isUndefined(options.template)) + return join(tmpDir, options.dir, options.template).replace( + TEMPLATE_PATTERN, + _randomChars(6) + ); + + // prefix and postfix + const name = [ + options.prefix ? options.prefix : "tmp", + "-", + _randomChars(12), + options.postfix ? "-" + options.postfix : "" + ].join(""); + + return join(tmpDir, options.dir, name); +} + +function _indexedDbExists(name: string) { + return new Promise(resolve => { + const req = indexedDB.open(name); + let existed = true; + req.onsuccess = function () { + req.result.close(); + if (!existed) indexedDB.deleteDatabase(name); + resolve(existed); + }; + req.onupgradeneeded = function () { + existed = false; + }; + }); +} + +/** + * Gets a temporary file name. + * + * @param {(Options)} opts options + */ +function tmpName(options: TmpNameOptions) { + const opts = _parseArguments(options); + + _assertAndSanitizeOptions(opts); + + let tries = opts.tries; + + return (async function _getUniqueName() { + const name = _generateTmpName(opts); + + // check whether the path exists then retry if needed + const exists = await _indexedDbExists(name); + if (exists) { + if (tries-- > 0) return _getUniqueName(); + + throw new Error( + "Could not get a unique tmp filename, max tries reached " + name + ); + } + + return name; + })(); +} + +function _prepareTmpDirRemoveCallback(name: string, options: DirOptions) { + const removeCallback = () => { + return new Promise((resolve, reject) => { + const request = indexedDB.deleteDatabase(name); + request.onerror = function (e) { + reject(); + }; + + request.onsuccess = function () { + resolve(void 0); + }; + }); + }; + if (!options.keep) _removeObjects.unshift(removeCallback); + return removeCallback; +} + +function _assertAndSanitizeOptions(options: DirOptions) { + options.tmpdir = _getTmpDir(options); + + const tmpDir = options.tmpdir; + + if (!_isUndefined(options.name)) + _assertIsRelative(options.name, "name", tmpDir); + + if (!_isUndefined(options.dir)) _assertIsRelative(options.dir, "dir", tmpDir); + + if (!_isUndefined(options.template)) { + _assertIsRelative(options.template, "template", tmpDir); + if (!options.template.match(TEMPLATE_PATTERN)) + throw new Error(`Invalid template, found "${options.template}".`); + } + + if ( + (!_isUndefined(options.tries) && isNaN(options.tries)) || + options.tries < 0 + ) + throw new Error(`Invalid tries, found "${options.tries}".`); + + options.tries = _isUndefined(options.name) + ? options.tries || DEFAULT_TRIES + : 1; + options.keep = !!options.keep; + + // sanitize dir, also keep (multiple) blanks if the user, purportedly sane, requests us to + options.dir = _isUndefined(options.dir) + ? "" + : relative(tmpDir, _resolvePath(options.dir, tmpDir)); + options.template = _isUndefined(options.template) + ? undefined + : relative(tmpDir, _resolvePath(options.template, tmpDir)); + // sanitize further if template is relative to options.dir + options.template = _isBlank(options.template) + ? undefined + : relative(options.dir, options.template); + + options.name = _isUndefined(options.name) + ? undefined + : _sanitizeName(options.name); + options.prefix = _isUndefined(options.prefix) ? "" : options.prefix; + options.postfix = _isUndefined(options.postfix) ? "" : options.postfix; +} + +/** + * Resolve the specified path name in respect to tmpDir. + * + * The specified name might include relative path components, e.g. ../ + * so we need to resolve in order to be sure that is is located inside tmpDir + * + * @param name + * @param tmpDir + * @returns {string} + * @private + */ +function _resolvePath(name: string, tmpDir: string) { + const sanitizedName = _sanitizeName(name); + if (sanitizedName.startsWith(tmpDir)) { + return resolve(sanitizedName); + } else { + return resolve(join(tmpDir, sanitizedName)); + } +} + +/** + * Sanitize the specified path name by removing all quote characters. + * + * @param name + * @returns {string} + * @private + */ +function _sanitizeName(name: string) { + if (_isBlank(name)) { + return name; + } + return name.replace(/["']/g, ""); +} + +/** + * Asserts whether specified name is relative to the specified tmpDir. + * + * @param {string} name + * @param {string} option + * @param {string} tmpDir + * @throws {Error} + * @private + */ +function _assertIsRelative( + name: string, + option: "name" | "dir" | "template", + tmpDir: string +) { + if (option === "name") { + // assert that name is not absolute and does not contain a path + if (isAbsolute(name)) + throw new Error( + `${option} option must not contain an absolute path, found "${name}".` + ); + // must not fail on valid . or .. or similar such constructs + let _basename = basename(name); + if (_basename === ".." || _basename === "." || _basename !== name) + throw new Error( + `${option} option must not contain a path, found "${name}".` + ); + } else { + // if (option === 'dir' || option === 'template') { + // assert that dir or template are relative to tmpDir + if (isAbsolute(name) && !name.startsWith(tmpDir)) { + throw new Error( + `${option} option must be relative to "${tmpDir}", found "${name}".` + ); + } + let resolvedPath = _resolvePath(name, tmpDir); + if (!resolvedPath.startsWith(tmpDir)) + throw new Error( + `${option} option must be relative to "${tmpDir}", found "${resolvedPath}".` + ); + } +} + +function _parseArguments(options: DirOptions): DirOptions { + if (_isUndefined(options)) { + return {}; + } + // copy options so we do not leak the changes we make internally + const actualOptions = {}; + for (const key of Object.getOwnPropertyNames(options)) { + actualOptions[key] = options[key]; + } + + return actualOptions; +} + +/** + * Creates a temporary directory. + * + * @param {(Options)} opts the options + */ +export async function dir(options: DirOptions) { + const opts = _parseArguments(options); + // gets a temporary filename + const path = await tmpName(opts); + return { + path, + cleanup: _prepareTmpDirRemoveCallback(path, options) + }; +} + +/** + * Sets the graceful cleanup. + * + * If graceful cleanup is set, tmp will remove all controlled temporary objects on process exit, otherwise the + * temporary objects will remain in place, waiting to be cleaned up on system restart or otherwise scheduled temporary + * object removals. + */ +export function setGracefulCleanup() { + _gracefulCleanup = true; +} + +/** + * Returns the currently configured tmp dir. + * + * @private + * @param {?Options} options + * @returns {string} the currently configured tmp dir + */ +function _getTmpDir(options: TmpNameOptions) { + return resolve(_sanitizeName((options && options.tmpdir) || "/tmp")); +} + +// window.addEventListener("beforeunload", _garbageCollector); diff --git a/src/packages/ganache/webpack/webpack.browser.config.ts b/src/packages/ganache/webpack/webpack.browser.config.ts new file mode 100644 index 0000000000..ac8ae380e2 --- /dev/null +++ b/src/packages/ganache/webpack/webpack.browser.config.ts @@ -0,0 +1,41 @@ +import base from "./webpack.common.config"; +import webpack from "webpack"; +import path from "path"; +import merge from "webpack-merge"; + +const config: webpack.Configuration = merge({}, base, { + resolve: { + extensions: [".tsx", ".ts", ".js"], + fallback: { + //#region node polyfills + util: require.resolve("util/"), + crypto: require.resolve("crypto-browserify"), + path: require.resolve("path-browserify"), + assert: require.resolve("assert/"), + stream: require.resolve("stream-browserify/"), + os: require.resolve("os-browserify/browser"), + process: require.resolve("process/browser"), + events: require.resolve("events/"), + buffer: require.resolve("buffer/"), + fs: false + //#endregion node polyfills + }, + alias: { + "tmp-promise": require.resolve("./polyfills/browser-tmp-promise"), + "bigint-buffer": require.resolve("./polyfills/browser-bigint-buffer"), + // replace leveldown with a browser version + leveldown: require.resolve("level-js/"), + // browser version can't start a server, so just remove the websocket server since it can't work anyway + "uWebSockets.js": false + } + }, + output: { + path: path.resolve(__dirname, "../", "dist", "web") + }, + plugins: [ + new webpack.ProvidePlugin({ Buffer: ["buffer", "Buffer"] }), + new webpack.ProvidePlugin({ process: ["process"] }) + ] +}); + +export default config; diff --git a/src/packages/ganache/webpack/webpack.cli.config.ts b/src/packages/ganache/webpack/webpack.cli.config.ts new file mode 100644 index 0000000000..3c78cea72c --- /dev/null +++ b/src/packages/ganache/webpack/webpack.cli.config.ts @@ -0,0 +1,31 @@ +import base from "./webpack.common.config"; +import webpack from "webpack"; +import path from "path"; +import merge from "webpack-merge"; + +const config: webpack.Configuration = merge({}, base, { + entry: "./src/cli.ts", + target: "node10.7", + output: { + path: path.resolve(__dirname, "../", "dist", "cli") + }, + externals: ["bigint-buffer", "leveldown", "secp256k1", "keccak"], + plugins: [ + new webpack.BannerPlugin({ banner: "#!/usr/bin/env node", raw: true }) + ], + module: { + rules: [ + { + // webpack load native modules + test: /\.node$/, + loader: "node-loader" + }, + { + test: /cli.ts$/, + use: "shebang-loader" + } + ] + } +}); + +export default config; diff --git a/src/packages/ganache/webpack/webpack.common.config.ts b/src/packages/ganache/webpack/webpack.common.config.ts new file mode 100644 index 0000000000..be145ce551 --- /dev/null +++ b/src/packages/ganache/webpack/webpack.common.config.ts @@ -0,0 +1,41 @@ +import webpack from "webpack"; + +// inlines files, like package.json +import packageJsonTransformer from "ts-transformer-inline-file/transformer"; + +const base: webpack.Configuration = { + entry: "./index.ts", + devtool: "source-map", + module: { + rules: [ + { + test: /\.tsx?$/, + use: [ + { + loader: "ts-loader", + options: { + getCustomTransformers: program => ({ + before: [packageJsonTransformer(program)] + }) + } + } + ], + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [".tsx", ".ts", ".js"] + }, + output: { + filename: "ganache.min.js", + library: "Ganache", + libraryExport: "default", + libraryTarget: "umd" + }, + stats: { + colors: true + } +}; + +export default base; diff --git a/src/packages/ganache/webpack/webpack.node.config.ts b/src/packages/ganache/webpack/webpack.node.config.ts new file mode 100644 index 0000000000..babd9f0162 --- /dev/null +++ b/src/packages/ganache/webpack/webpack.node.config.ts @@ -0,0 +1,23 @@ +import base from "./webpack.common.config"; +import webpack from "webpack"; +import path from "path"; +import merge from "webpack-merge"; + +const config: webpack.Configuration = merge({}, base, { + target: "node10.7", + output: { + path: path.resolve(__dirname, "../", "dist", "node") + }, + externals: ["leveldown", "secp256k1", "keccak"], + module: { + rules: [ + { + // webpack load native modules + test: /\.node$/, + loader: "node-loader" + } + ] + } +}); + +export default config; diff --git a/src/packages/options/.npmignore b/src/packages/options/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/packages/options/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/packages/options/LICENSE b/src/packages/options/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/packages/options/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/packages/options/README.md b/src/packages/options/README.md new file mode 100644 index 0000000000..177621cbe7 --- /dev/null +++ b/src/packages/options/README.md @@ -0,0 +1,3 @@ +# `@ganache/options` + +Ganache's server/provider options TypeScript types diff --git a/src/packages/options/index.ts b/src/packages/options/index.ts new file mode 100644 index 0000000000..7a9075164c --- /dev/null +++ b/src/packages/options/index.ts @@ -0,0 +1,11 @@ +export * from "./src/base"; +export { + Options, + LegacyOptions, + Legacy, + OptionName, + OptionRawType +} from "./src/getters"; +export * from "./src/exclusive"; +export * from "./src/definition"; +export * from "./src/create"; diff --git a/src/packages/options/npm-shrinkwrap.json b/src/packages/options/npm-shrinkwrap.json new file mode 100644 index 0000000000..7f40e07aef --- /dev/null +++ b/src/packages/options/npm-shrinkwrap.json @@ -0,0 +1,387 @@ +{ + "name": "@ganache/options", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" + }, + "@types/seedrandom": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.28.tgz", + "integrity": "sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "bip39": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz", + "integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==", + "requires": { + "@types/node": "11.11.6", + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "google-closure-compiler": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20201102.0.1.tgz", + "integrity": "sha512-Cz+1jOswH0MwMVPu1rRH1xD4KYuY5XW2ox5aXwqaAxevqmirhr36f8wgKPHuVRSovFejW640r6UFwyrOT6U0CA==", + "dev": true, + "requires": { + "chalk": "2.x", + "google-closure-compiler-java": "^20201102.0.1", + "google-closure-compiler-linux": "^20201102.0.1", + "google-closure-compiler-osx": "^20201102.0.1", + "google-closure-compiler-windows": "^20201102.0.1", + "minimist": "1.x", + "vinyl": "2.x", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "google-closure-compiler-java": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20201102.0.1.tgz", + "integrity": "sha512-pXJIlyqepHhih0HCbShkAZJyViIxdyd4V7MnCUZEXLIIlygw92e2dC+5XiONDQZgRlF93BPmWCy9jr7wYoW1hQ==", + "dev": true + }, + "google-closure-compiler-linux": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20201102.0.1.tgz", + "integrity": "sha512-aRbyTGnQoFXchcpEFNrP1p/WIvYOgN3hYKI+MOHWkvwVJBY2P8gpb07hAigO8fj+QKD/SFCl+2pXP+JniWOEqw==", + "dev": true, + "optional": true + }, + "google-closure-compiler-osx": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20201102.0.1.tgz", + "integrity": "sha512-VguqEAOYI6XYZN6JcLMP8fpsoXk1Z9YuntMjv0IDVydkbZaHYOI4zE39FJhMuWiN7gOzSX2b/BBC6GsSh1F3fw==", + "dev": true, + "optional": true + }, + "google-closure-compiler-windows": { + "version": "20201102.0.1", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20201102.0.1.tgz", + "integrity": "sha512-LlynipQi/iP76mjkOu6Rc1mCRuxTAhRvLjq10aGfVjKwpbCAF0Jq2a5k2ygr4xYiINNi2/L2qUw6ObPm9wQCOw==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + } + } +} diff --git a/src/packages/options/package.json b/src/packages/options/package.json new file mode 100644 index 0000000000..4b5bdb1259 --- /dev/null +++ b/src/packages/options/package.json @@ -0,0 +1,51 @@ +{ + "name": "@ganache/options", + "version": "0.1.0", + "description": "Ganache's server/provider options TypeScript types", + "author": "David Murdoch (https://davidmurdoch.com)", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/packages/options#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "source": "index.ts", + "directories": { + "lib": "lib" + }, + "files": [ + "lib" + ], + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/packages/options" + }, + "scripts": { + "tsc": "ttsc" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ganache-options", + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling" + ], + "dependencies": { + "@ganache/utils": "^0.1.0", + "bip39": "3.0.2", + "seedrandom": "3.0.5" + }, + "devDependencies": { + "@types/seedrandom": "2.4.28", + "google-closure-compiler": "20201102.0.1" + } +} diff --git a/src/packages/options/src/base.ts b/src/packages/options/src/base.ts new file mode 100644 index 0000000000..5f5cc59789 --- /dev/null +++ b/src/packages/options/src/base.ts @@ -0,0 +1,21 @@ +export namespace Base { + export type Option = { + rawType?: unknown; + type: unknown; + hasDefault?: true; + legacy?: { + [name: string]: unknown; + }; + }; + + export type ExclusiveGroupOptionName = string; + export type ExclusiveGroup = ExclusiveGroupOptionName[]; + + export type Config = { + options: { + [optionName: string]: Option; + }; + + exclusiveGroups?: ExclusiveGroup[]; + }; +} diff --git a/src/packages/options/src/create.ts b/src/packages/options/src/create.ts new file mode 100644 index 0000000000..45426ec33f --- /dev/null +++ b/src/packages/options/src/create.ts @@ -0,0 +1,84 @@ +import { Definitions, ExternalConfig, InternalConfig } from "./definition"; +import { Base } from "./base"; +import { UnionToTuple } from "./exclusive"; + +import { utils } from "@ganache/utils"; + +const hasOwn = utils.hasOwn; + +type Options = { [key: string]: Base.Config }; + +export type ProviderOptions = Partial< + { + [K in keyof O]: ExternalConfig; + } +>; + +export type InternalOptions = { + [K in keyof O]: InternalConfig; +}; + +export type Defaults = { + [K in keyof O]: Definitions; +}; + +function fill(defaults: any, options: any, target: any, namespace: any) { + const def = defaults[namespace]; + const config = (target[namespace] = target[namespace] || {}); + + if (hasOwn(options, namespace)) { + const namespaceOptions = options[namespace]; + + const keys = Object.keys(def); + for (let i = 0, l = keys.length; i < l; i++) { + const key = keys[i]; + const propDefinition = def[key]; + let value = namespaceOptions[key]; + if (value !== undefined) { + config[key] = propDefinition.normalize(namespaceOptions[key]); + } else { + const legacyName = propDefinition.legacyName || key; + value = options[legacyName]; + if (value !== undefined) { + config[key] = propDefinition.normalize(value); + } else if (hasOwn(propDefinition, "default")) { + config[key] = propDefinition.default(config); + } + } + } + } else { + const keys = Object.keys(def); + for (let i = 0, l = keys.length; i < l; i++) { + const key = keys[i]; + const propDefinition = def[key]; + + const legacyName = propDefinition.legacyName || key; + const value = options[legacyName]; + if (value !== undefined) { + config[key] = propDefinition.normalize(value); + } else if (hasOwn(propDefinition, "default")) { + config[key] = propDefinition.default(config); + } + } + } +} + +export class OptionsConfig { + #defaults: Defaults; + #namespaces: UnionToTuple>; + + constructor(defaults: Defaults) { + this.#defaults = defaults; + this.#namespaces = Object.keys(defaults) as UnionToTuple>; + } + + normalize(options: ProviderOptions) { + const defaults = this.#defaults; + + const out = {} as InternalOptions; + this.#namespaces.forEach(namespace => { + fill(defaults, options, out, namespace as keyof Defaults); + }); + return out; + } +} diff --git a/src/packages/options/src/definition.ts b/src/packages/options/src/definition.ts new file mode 100644 index 0000000000..217c99b6ed --- /dev/null +++ b/src/packages/options/src/definition.ts @@ -0,0 +1,44 @@ +import { Base } from "./base"; +import { ExclusiveGroupUnionAndUnconstrainedPlus } from "./exclusive"; +import { + Legacy, + OptionHasDefault, + OptionHasLegacy, + OptionName, + OptionRawType, + OptionType +} from "./getters"; + +//#region Definition helpers +type Normalize< + C extends Base.Config, + N extends OptionName = OptionName +> = (rawInput: OptionRawType) => OptionType; + +export type ExternalConfig = Partial< + ExclusiveGroupUnionAndUnconstrainedPlus +>; + +export type InternalConfig< + C extends Base.Config +> = ExclusiveGroupUnionAndUnconstrainedPlus; + +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( + k: infer I +) => void + ? I + : never; + +export type Definitions = { + [N in OptionName]: { + readonly normalize: Normalize; + } & (void extends OptionHasDefault + ? {} + : { readonly default: (config: InternalConfig) => OptionType }) & + (void extends OptionHasLegacy + ? {} + : { + readonly legacyName: UnionToIntersection>; + }); +}; +//#endregion Definition helpers diff --git a/src/packages/options/src/exclusive.ts b/src/packages/options/src/exclusive.ts new file mode 100644 index 0000000000..51a89e6466 --- /dev/null +++ b/src/packages/options/src/exclusive.ts @@ -0,0 +1,186 @@ +import { Base } from "./base"; +import { + OptionName, + Option, + ExclusiveGroupIndex, + ExclusiveGroups, + Options, + OptionType, + OptionRawType +} from "./getters"; + +//#region options not part of exclusive groups +type UnconstrainedOptions = Omit< + Options, + ExclusiveGroupOptionName +>; +type UnconstrainedOptionName = string & + keyof UnconstrainedOptions; +type UnconstrainedOptionsByType< + C extends Base.Config, + T extends "type" | "rawType" +> = { + [N in UnconstrainedOptionName]: T extends "type" + ? OptionType + : OptionRawType; +}; +//#endregion options not part of exclusive groups + +//#region exclusive group options helpers +type ExclusiveGroupOptionPairs< + C extends Base.Config, + G extends unknown[] +> = G extends [] + ? [] + : G extends [infer N, ...infer R] + ? [ + [N, ExclusiveGroupOptionNameOption], + ...ExclusiveGroupOptionPairs + ] + : never; + +type ExclusiveGroupOptionNameOption< + C extends Base.Config, + N +> = N extends OptionName ? Option : never; +type PairsToMapping = T extends [] + ? {} + : T extends [[infer N, infer O], ...infer R] + ? { + [N_ in string & N]: O; + } & + PairsToMapping + : never; + +type RequireOnly = Pick & Partial>; + +type ExclusiveGroupOptionalUnionByName< + C extends Base.Config, + GRP extends ExclusiveGroup, + M extends OptionName, + T extends "rawType" | "type" +> = { + [K in keyof RequireOnly, M>]: K extends M + ? T extends "type" + ? OptionType + : OptionRawType + : never; +}; + +type Combine< + C extends Base.Config, + O extends unknown, + GRP extends ExclusiveGroup, + T extends "rawType" | "type" +> = { + [N in keyof GRP]: GRP[N] extends OptionName + ? { + [Key in keyof (ExclusiveGroupOptionalUnionByName & + UnconstrainedOptionsByType & + O)]: Key extends keyof ExclusiveGroupOptionalUnionByName< + C, + GRP, + GRP[N], + T + > + ? ExclusiveGroupOptionalUnionByName[Key] + : Key extends keyof UnconstrainedOptionsByType + ? UnconstrainedOptionsByType[Key] + : Key extends keyof O + ? O[Key] + : never; + } + : never; +} extends { [n: number]: infer I } + ? I + : never; + +type IsNeverType = [T] extends [never] ? true : never; +export type ExclusiveGroupUnionAndUnconstrainedPlus< + C extends Base.Config, + T extends "rawType" | "type", + GRPS extends ExclusiveGroups = ExclusiveGroups, + O extends unknown[] = [] +> = GRPS extends [infer GRP, ...infer Rest] + ? GRP extends ExclusiveGroup + ? Rest extends any[] + ? O extends [] + ? // first time through + ExclusiveGroupUnionAndUnconstrainedPlus< + C, + T, + Rest, + UnionToTuple> + > + : // recurse + ExclusiveGroupUnionAndUnconstrainedPlus< + C, + T, + Rest, + UnionToTuple< + { + // iterate over each object in the O tuple. + // Omit makes it include only the indexes, but + // TypeScript will treat it as an object now, so we `UnionToTuple` + // to turn it back into a Tuple + [OK in keyof Omit]: Combine; + } extends { [n: number]: infer I } + ? I + : never + > + > + : never + : never + : O extends { [n: number]: infer I } + ? // if there are no exclusiveGroups `I` is `never` so we return `C` + // directly + true extends IsNeverType + ? { + [Key in keyof UnconstrainedOptionsByType< + C, + T + >]: UnconstrainedOptionsByType[Key]; + } + : I + : never; + +//#region UnionToTuple +export type UnionToTuple = ( + (T extends any ? (t: T) => T : never) extends infer U + ? (U extends any ? (u: U) => any : never) extends (v: infer V) => any + ? V + : never + : never +) extends (_: any) => infer W + ? [...UnionToTuple>, W] + : []; +//#endregion + +//#endregion exclusive group options helpers + +//#region exclusive groups +type ExclusiveGroup< + C extends Base.Config, + K extends ExclusiveGroupIndex = ExclusiveGroupIndex +> = ExclusiveGroups[K]; + +type ExclusiveGroupOptionName< + C extends Base.Config, + K extends ExclusiveGroupIndex = ExclusiveGroupIndex +> = Extract, DeepTupleToUnion>>; + +type DeepTupleToUnion = T extends [] // empty tuple case (base case) + ? never + : T extends [infer N, ...infer R] // inductive case + ? N extends unknown[] + ? DeepTupleToUnion | DeepTupleToUnion + : N | DeepTupleToUnion + : never; // we should never hit this case +//#endregion exclusive groups + +//#region options separated by exclusive group +type ExclusiveGroupOptionsByGroup< + C extends Base.Config, + G extends ExclusiveGroup +> = PairsToMapping>; +//#endregion diff --git a/src/packages/options/src/getters.ts b/src/packages/options/src/getters.ts new file mode 100644 index 0000000000..6897d2eb30 --- /dev/null +++ b/src/packages/options/src/getters.ts @@ -0,0 +1,55 @@ +import { Base } from "./base"; + +//#region getters for buckets +export type Options = C["options"]; +export type ExclusiveGroups = C["exclusiveGroups"]; +//#endregion + +//#region getters for keys +export type OptionName = keyof Options; +export type ExclusiveGroupIndex = number & + keyof ExclusiveGroups; +//#endregion + +//#region getters for individual things +export type Option< + C extends Base.Config, + N extends OptionName = OptionName +> = Options[N]; +//#endregion + +//#region getters for option +export type OptionRawType< + C extends Base.Config, + N extends OptionName = OptionName +> = void extends Option["rawType"] + ? Option["type"] + : Option["rawType"]; + +export type OptionType< + C extends Base.Config, + N extends OptionName = OptionName +> = Option["type"]; + +export type OptionHasDefault< + C extends Base.Config, + N extends OptionName = OptionName +> = Option["hasDefault"]; + +export type OptionHasLegacy< + C extends Base.Config, + N extends OptionName = OptionName +> = Option["legacy"]; + +export type LegacyOptions = { + [K in keyof C["options"]]: C["options"][K] extends { legacy: any } + ? K + : never; +}[keyof C["options"]]; + +export type Legacy> = Option< + C, + N +>["legacy"]; + +//#endregion getters for option diff --git a/src/packages/options/tests/index.test.ts b/src/packages/options/tests/index.test.ts new file mode 100644 index 0000000000..2288012cc3 --- /dev/null +++ b/src/packages/options/tests/index.test.ts @@ -0,0 +1,7 @@ +"use strict"; + +const options = require(".."); + +describe("@ganache/options", () => { + it("needs tests"); +}); diff --git a/src/packages/options/tsconfig.json b/src/packages/options/tsconfig.json new file mode 100644 index 0000000000..25d5c3cf7e --- /dev/null +++ b/src/packages/options/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts"] +} diff --git a/src/packages/promise-queue/.npmignore b/src/packages/promise-queue/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/packages/promise-queue/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/packages/promise-queue/LICENSE b/src/packages/promise-queue/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/packages/promise-queue/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/packages/promise-queue/README.md b/src/packages/promise-queue/README.md new file mode 100644 index 0000000000..f9807bd8c9 --- /dev/null +++ b/src/packages/promise-queue/README.md @@ -0,0 +1,3 @@ +# `@ganache/promise-queue` + +A queue that resolves Promise instances in first-in first-out order. diff --git a/src/packages/promise-queue/index.ts b/src/packages/promise-queue/index.ts new file mode 100644 index 0000000000..2ff0738700 --- /dev/null +++ b/src/packages/promise-queue/index.ts @@ -0,0 +1,108 @@ +import Emittery from "emittery"; +import Entry from "./src/entry"; + +const emitteryMethods = ["emit", "once"] as const; + +/** + * Creates a FIFO queue to that ensures promises are _resolved_ in the order + * they were added. + * + * This is different than a FIFO queue that _executes_ functions that + * return promises; this queue is for the promises themselves. + * + * @example + * ```javascript + * const queue = new PromiseQueue(); + * + * const slow = new Promise(resolve => setTimeout(resolve, 1000, "slow")); + * const fast = Promise.resolve("fast"); + * + * await Promise.race([ + * queue.add(slow), + * queue.add(fast) + * ]); // returns "slow" + * + * Additionally, the queued promise chain can be cleared via `queue.clear(value)`. + * This will cause the chain of promises to all resolve immediately with the + * given value. * + * + * * note: whatever the promise starting doing when it was created will still + * happen, no promises are aborted; rather, the return value is ignored. + * ``` + */ +@Emittery.mixin(Symbol.for("emittery"), emitteryMethods) +class PromiseQueue { + /** + * Returns true if there are promises pending in the queue + */ + public isBusy() { + return this.#queue.length !== 0; + } + + // TODO(perf): a singly linked list is probably a better option here + readonly #queue: Entry[] = []; + + #tryResolve = (queue: Entry[], entry: Entry) => { + // if this is now the highest priority entry, resolve the outer + // Promise + if (entry === queue[0]) { + queue.shift(); + entry.resolve(entry.value); + // then try resolving the rest + this.#tryResolveChain(queue); + } else { + entry.resolved = true; + } + }; + + /** + * Adds the promise to the end of the queue. + * @param promise + * @returns a promise that resolves with the given promise's result. If the + * queue was `clear`ed before the promise could be shifted off the return + * value will be the `value` passed to `clear`. + */ + add(promise: Promise) { + const queue = this.#queue; + const entry: Entry = new Entry(promise, queue, this.#tryResolve); + queue.push(entry); + return entry.promise; + } + + /** + * Clears all promises from the queue and sets their resolved values to the + * given value. + */ + clear(value: T) { + // remove all entrys from the queue and mark them. + const cancelledQueue = this.#queue.splice(0); + cancelledQueue.forEach(entry => { + entry.queue = cancelledQueue; + entry.value = value; + }); + } + + /** + * Removes all _resolved_ promises from the front of the chain of promises. + */ + #tryResolveChain = (queue: Entry[]) => { + let first = queue[0]; + while (first && first.resolved) { + queue.shift(); + first.resolve(first.value); + first = queue[0]; + } + + // if there is nothing left to do emit `"idle"` + if (queue.length === 0) { + this.emit("idle"); + } + }; +} + +interface PromiseQueue + extends Pick { + emittery: Emittery; +} + +export default PromiseQueue; diff --git a/src/packages/promise-queue/npm-shrinkwrap.json b/src/packages/promise-queue/npm-shrinkwrap.json new file mode 100644 index 0000000000..3f55a05c8c --- /dev/null +++ b/src/packages/promise-queue/npm-shrinkwrap.json @@ -0,0 +1,13 @@ +{ + "name": "@ganache/promise-queue", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "emittery": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", + "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==" + } + } +} diff --git a/src/packages/promise-queue/package.json b/src/packages/promise-queue/package.json new file mode 100644 index 0000000000..4fdf5beb6c --- /dev/null +++ b/src/packages/promise-queue/package.json @@ -0,0 +1,49 @@ +{ + "name": "@ganache/promise-queue", + "version": "0.1.0", + "description": "A queue that resolves Promise instances in first-in first-out order.", + "author": "David Murdoch (https://davidmurdoch.com)", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/packages/promise-queue#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "source": "index.ts", + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "lib" + ], + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/packages/promise-queue" + }, + "scripts": { + "tsc": "ttsc", + "test": "nyc npm run mocha", + "mocha": "cross-env TS_NODE_COMPILER=ttypescript TS_NODE_FILES=true mocha --exit --require ts-node/register --recursive --check-leaks 'tests/**.ts'" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ganache-promise-queue", + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling" + ], + "dependencies": { + "emittery": "0.7.2" + }, + "devDependencies": {} +} diff --git a/src/packages/promise-queue/src/entry.ts b/src/packages/promise-queue/src/entry.ts new file mode 100644 index 0000000000..5b59c0cb77 --- /dev/null +++ b/src/packages/promise-queue/src/entry.ts @@ -0,0 +1,25 @@ +export default class Entry { + public readonly promise: Promise; + public resolve: (value: T | PromiseLike) => void; + + public value: T | Promise; + public queue: Entry[]; + + public resolved = false; + public onSetteled: (queue: Entry[], entry: Entry) => void; + + constructor( + promise: Promise, + queue: Entry[], + onSetteled: (queue: Entry[], entry: Entry) => void + ) { + this.value = promise; + this.queue = queue; + this.onSetteled = onSetteled; + const _onSetteled = () => this.onSetteled(this.queue, this); + promise.then(_onSetteled, _onSetteled); + this.promise = new Promise(resolve => { + this.resolve = resolve; + }); + } +} diff --git a/src/packages/promise-queue/tests/index.test.ts b/src/packages/promise-queue/tests/index.test.ts new file mode 100644 index 0000000000..d7f1dac8c2 --- /dev/null +++ b/src/packages/promise-queue/tests/index.test.ts @@ -0,0 +1,6 @@ +import assert from "assert"; +import PromiseQueue from ".."; + +describe("@ganache/promise-queue", () => { + it("needs tests"); +}); diff --git a/src/packages/promise-queue/tsconfig.json b/src/packages/promise-queue/tsconfig.json new file mode 100644 index 0000000000..25d5c3cf7e --- /dev/null +++ b/src/packages/promise-queue/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts"] +} diff --git a/src/packages/utils/.npmignore b/src/packages/utils/.npmignore new file mode 100644 index 0000000000..115ab4f024 --- /dev/null +++ b/src/packages/utils/.npmignore @@ -0,0 +1,8 @@ +./index.ts +tests +.nyc_output +coverage +scripts +src +tsconfig.json +typedoc.json diff --git a/src/packages/utils/LICENSE b/src/packages/utils/LICENSE new file mode 100644 index 0000000000..39f3b14498 --- /dev/null +++ b/src/packages/utils/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Truffle Blockchain Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/packages/utils/README.md b/src/packages/utils/README.md new file mode 100644 index 0000000000..0368a05105 --- /dev/null +++ b/src/packages/utils/README.md @@ -0,0 +1,3 @@ +# `@ganache/utils` + +Utility functions for @ganache packages. diff --git a/src/packages/utils/index.ts b/src/packages/utils/index.ts new file mode 100644 index 0000000000..236ca0179c --- /dev/null +++ b/src/packages/utils/index.ts @@ -0,0 +1,7 @@ +export * as types from "./src/types"; +export * as utils from "./src/utils"; +export * as JsonRpc from "./src/things/json-rpc"; +export * from "./src/things/json-rpc/json-rpc-quantity"; +export * from "./src/things/json-rpc/json-rpc-data"; +export { default as JsonRpcTypes } from "./src/things/jsonrpc"; +export { default as PromiEvent } from "./src/things/promievent"; diff --git a/src/packages/utils/npm-shrinkwrap.json b/src/packages/utils/npm-shrinkwrap.json new file mode 100644 index 0000000000..5499a0fbaa --- /dev/null +++ b/src/packages/utils/npm-shrinkwrap.json @@ -0,0 +1,42 @@ +{ + "name": "@ganache/utils", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "optional": true, + "requires": { + "bindings": "^1.3.0" + } + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "emittery": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", + "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "uWebSockets.js": { + "version": "github:uNetworking/uWebSockets.js#3dbec7b56d627193e20705844b6bd10e49848b8c", + "from": "github:uNetworking/uWebSockets.js#v18.4.0", + "dev": true + } + } +} diff --git a/src/packages/utils/package.json b/src/packages/utils/package.json new file mode 100644 index 0000000000..e3baa76ca1 --- /dev/null +++ b/src/packages/utils/package.json @@ -0,0 +1,55 @@ +{ + "name": "@ganache/utils", + "version": "0.1.0", + "description": "Utility functions for @ganache packages", + "author": "David Murdoch (https://davidmurdoch.com)", + "homepage": "https://github.com/trufflesuite/ganache-core/tree/develop/src/packages/utils#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "source": "index.ts", + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "lib" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/trufflesuite/ganache-core.git", + "directory": "src/packages/utils" + }, + "scripts": { + "tsc": "ttsc" + }, + "bugs": { + "url": "https://github.com/trufflesuite/ganache-core/issues" + }, + "keywords": [ + "ganache", + "ganache-utils", + "ethereum", + "evm", + "blockchain", + "smart contracts", + "dapps", + "solidity", + "vyper", + "fe", + "web3", + "tooling" + ], + "dependencies": { + "emittery": "0.7.2" + }, + "devDependencies": { + "uWebSockets.js": "github:uNetworking/uWebSockets.js#v18.4.0" + }, + "optionalDependencies": { + "bigint-buffer": "1.1.5" + } +} diff --git a/src/packages/utils/src/things/json-rpc/index.ts b/src/packages/utils/src/things/json-rpc/index.ts new file mode 100644 index 0000000000..d7dd7bea53 --- /dev/null +++ b/src/packages/utils/src/things/json-rpc/index.ts @@ -0,0 +1 @@ +export { JsonRpcType } from "./json-rpc-base-types"; diff --git a/src/packages/utils/src/things/json-rpc/json-rpc-base-types.ts b/src/packages/utils/src/things/json-rpc/json-rpc-base-types.ts new file mode 100644 index 0000000000..8de25c06ec --- /dev/null +++ b/src/packages/utils/src/things/json-rpc/json-rpc-base-types.ts @@ -0,0 +1,108 @@ +import { bigIntToBuffer } from "../../utils"; +import { uintToBuffer } from "../../utils"; + +import { BUFFER_EMPTY } from "../../utils/constants"; + +export const strCache = new WeakMap(); +export const bufCache = new WeakMap(); +export const toStrings = new WeakMap(); +export const toBuffers = new WeakMap(); + +const inspect = Symbol.for("nodejs.util.inspect.custom"); + +export class BaseJsonRpcType< + T extends number | bigint | string | Buffer = + | number + | bigint + | string + | Buffer +> { + public [Symbol.toStringTag]: string; + + protected value: T; + // used to make console.log debugging a little easier + private [inspect](_depth: number, _options: any): T { + return this.value; + } + constructor(value: T) { + const self = this; + if (Buffer.isBuffer(value)) { + toStrings.set(this, () => value.toString("hex")); + bufCache.set(this, value); + self[Symbol.toStringTag] = "Buffer"; + } else { + const type = typeof value; + switch (type) { + case "number": + if ((value as number) % 1 !== 0) { + throw new Error("`Cannot wrap a decimal value as a json-rpc type`"); + } + toStrings.set(this, () => (value as number).toString(16)); + toBuffers.set(this, () => uintToBuffer(value as number)); + break; + case "bigint": + toStrings.set(this, () => (value as bigint).toString(16)); + toBuffers.set(this, () => bigIntToBuffer(value as bigint)); + break; + case "string": { + // handle hex-encoded string + if ((value as string).indexOf("0x") === 0) { + strCache.set(this, (value as string).toLowerCase()); + toBuffers.set(this, () => { + let fixedValue = (value as string).slice(2); + if (fixedValue.length % 2 === 1) { + fixedValue = "0" + fixedValue; + } + return Buffer.from(fixedValue, "hex"); + }); + } else { + throw new Error( + `cannot convert string value "${value}" into type \`${this.constructor.name}\`; strings must be hex-encoded and prefixed with "0x".` + ); + } + break; + } + default: + // handle undefined/null + if (value == null) { + // This is a weird thing that returns undefined/null for a call + // to toString(). + this.toString = () => value as string; + bufCache.set(this, BUFFER_EMPTY); + break; + } + throw new Error(`Cannot wrap a "${type}" as a json-rpc type`); + } + self[Symbol.toStringTag] = type; + } + + this.value = value; + } + + toString(): string | null { + let str = strCache.get(this); + if (str === void 0) { + str = "0x" + toStrings.get(this)(); + strCache.set(this, str); + } + return str; + } + toBuffer(): Buffer { + let buf = bufCache.get(this); + if (buf === void 0) { + buf = toBuffers.get(this)(); + bufCache.set(this, buf); + } + return buf; + } + valueOf(): T | null { + return this.value; + } + toJSON(): string | null { + return this.toString(); + } +} + +export type JsonRpcType< + T extends number | bigint | string | Buffer +> = BaseJsonRpcType; diff --git a/src/packages/utils/src/things/json-rpc/json-rpc-data.ts b/src/packages/utils/src/things/json-rpc/json-rpc-data.ts new file mode 100644 index 0000000000..e0c06a4001 --- /dev/null +++ b/src/packages/utils/src/things/json-rpc/json-rpc-data.ts @@ -0,0 +1,58 @@ +import { BaseJsonRpcType } from "./json-rpc-base-types"; +import { strCache, toStrings } from "./json-rpc-base-types"; + +function validateByteLength(byteLength?: number) { + if (typeof byteLength !== "number" || byteLength < 0) { + throw new Error(`byteLength must be a number greater than 0`); + } +} +const byteLengths = new WeakMap(); +export class Data extends BaseJsonRpcType { + constructor(value: string | Buffer, byteLength?: number) { + if (typeof value === "bigint") { + throw new Error(`Cannot create a ${typeof value} as a Data`); + } + super(value); + if (byteLength !== void 0) { + validateByteLength(byteLength); + byteLengths.set(this, byteLength | 0); + } + } + public toString(byteLength?: number): string { + const str = strCache.get(this) as string; + if (str !== void 0) { + return str; + } else { + let str = toStrings.get(this)() as string; + let length = str.length; + if (length % 2 === 1) { + length++; + str = `0${str}`; + } + + if (byteLength !== void 0) { + validateByteLength(byteLength); + } else { + byteLength = byteLengths.get(this); + } + if (byteLength !== void 0) { + const strLength = byteLength * 2; + const padBy = strLength - length; + if (padBy < 0) { + // if our hex-encoded data is longer than it should be, truncate it: + str = str.slice(0, strLength); + } else if (padBy > 0) { + // if our hex-encoded data is shorter than it should be, pad it: + str = "0".repeat(padBy) + str; + } + } + return `0x${str}`; + } + } + public static from( + value: T, + byteLength?: number + ) { + return new Data(value, byteLength); + } +} diff --git a/src/packages/utils/src/things/json-rpc/json-rpc-quantity.ts b/src/packages/utils/src/things/json-rpc/json-rpc-quantity.ts new file mode 100644 index 0000000000..4d085941ea --- /dev/null +++ b/src/packages/utils/src/things/json-rpc/json-rpc-quantity.ts @@ -0,0 +1,89 @@ +import { BaseJsonRpcType } from "./json-rpc-base-types"; +import { toBigIntBE } from "bigint-buffer"; + +export class Quantity extends BaseJsonRpcType { + _nullable: boolean = false; + public static from( + value: number | bigint | string | Buffer, + nullable = false + ) { + if (value instanceof Quantity) return value; + const q = new Quantity(value); + q._nullable = nullable; + return q; + } + public toString(): string | null { + if (Buffer.isBuffer(this.value)) { + let val = this.value.toString("hex").replace(/^(?:0+(.+?))?$/, "$1"); + + if (val === "") { + if (this._nullable) { + return null; + } + // RPC Quantities must represent `0` as `0x0` + val = "0"; + } + return "0x" + val; + } else { + return super.toString(); + } + } + public toBigInt(): bigint | null { + const value = this.value; + + // TODO(perf): memoize this stuff + if (Buffer.isBuffer(value)) { + // Parsed as BE. + + // This doesn't handle negative values. We may need to add logic to handle + // it because it is possible values returned from the VM could be negative + // and stored in a buffer. + + const length = value.byteLength; + if (length === 0) { + return null; + } + // Buffers that are 6 bytes or less can be converted with built-in methods + if (length <= 6) { + return BigInt(value.readUIntBE(0, length)); + } + + let view: DataView; + // Buffers that are 7 bytes need to be padded to 8 bytes + if (length === 7) { + const padded = new Uint8Array(8); + // set byte 0 to 0, and bytes 1-8 to the value's 7 bytes: + padded.set(value, 1); + view = new DataView(padded.buffer); + } else if (length === 8) { + view = new DataView(value.buffer, value.byteOffset, length); + } else { + // TODO: toBigIntBE is a native lib with no pure JS fallback yet. + return toBigIntBE(value); + // TODO: handle bigint's stored as Buffers that are this big? + // It's not too hard. + // throw new Error(`Cannot convert Buffer of length ${length} to bigint!`); + } + return view.getBigUint64(0) as bigint; + } else { + return value != null ? BigInt(value) : 0n; + } + } + public toNumber() { + return typeof this.value === "number" + ? this.value + : Number(this.toBigInt()); + } + valueOf(): bigint { + const value = this.value; + if (value === null) { + return value as null; + } else if (value === undefined) { + return value as undefined; + } else { + return this.toBigInt(); + } + } +} + +export default Quantity; diff --git a/src/packages/utils/src/things/jsonrpc.ts b/src/packages/utils/src/things/jsonrpc.ts new file mode 100644 index 0000000000..41185fd18d --- /dev/null +++ b/src/packages/utils/src/things/jsonrpc.ts @@ -0,0 +1,77 @@ +import { Api, KnownKeys } from "../types"; +type JSError = Error; + +namespace JsonRpc { + const jsonrpc = "2.0"; + type JsonRpc = { + readonly id: string; + readonly jsonrpc: string; + toString(): string; + }; + export type Request = JsonRpc & { + readonly id: string; + readonly jsonrpc: string; + readonly method: KnownKeys; + readonly params?: any[]; + }; + export type Response = JsonRpc & { + readonly result: any; + }; + export type Error = JsonRpc & { + readonly error: { + readonly [key: string]: unknown; + readonly code: number; + readonly message: any; + }; + readonly result?: any; + }; + export const Request = (json: any): Request => { + return { + id: json.id, + jsonrpc, + method: json.method, + params: json.params + }; + }; + export const Response = (id: string, result: any): Response => { + return { + id: id, + jsonrpc, + result + }; + }; + export const Error = ( + id: string, + error: T, + result?: unknown + ): Error => { + type E = { [K in keyof T]: K extends string ? T[K] : never }; + // Error objects are weird, `message` isn't included in the property names, + // so it is pulled out separately. + const details = { message: error.message } as E; + Object.getOwnPropertyNames(error).forEach(name => { + if (typeof name === "string") { + details[name] = error[name]; + } + }); + if (typeof details.code !== "number") { + details.code = -32700; // JSON-RPC Parse error + } + if (result !== undefined) { + return { + id, + jsonrpc, + error: details, + result + }; + } else { + return { + id, + jsonrpc, + error: details + }; + } + }; +} + +export default JsonRpc; diff --git a/src/packages/utils/src/things/promievent.ts b/src/packages/utils/src/things/promievent.ts new file mode 100644 index 0000000000..4e2dbde175 --- /dev/null +++ b/src/packages/utils/src/things/promievent.ts @@ -0,0 +1,124 @@ +import Emittery from "emittery"; + +// PromiEvent's `resolve and `reject` need to return a PromiEvent, not just a +// Promise +declare var Promise: { + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch( + onrejected?: + | ((reason: any) => TResult | PromiseLike) + | undefined + | null + ): PromiEvent; + + /** + * Creates a new resolved promievent for the provided value. + * @param value A promise. + * @returns A promievent whose internal state matches the provided promise. + */ + resolve(value: T | PromiseLike): PromiEvent; + + /** + * Creates a new resolved promievent. + * @returns A resolved promievent. + */ + resolve(): PromiEvent; +} & PromiseConstructor; + +const emitteryMethods = [ + "clearListeners", + "once", + "on", + "emit", + "onAny" +] as const; + +@Emittery.mixin(Symbol.for("emittery"), emitteryMethods) +class PromiEvent extends Promise { + constructor( + executor: ( + resolve: (value?: T | PromiseLike) => void, + reject: (reason?: any) => void + ) => void + ) { + super(executor); + } + + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A PromiEvent for the completion of the callback. + */ + catch( + onrejected?: + | ((reason: any) => TResult | PromiseLike) + | undefined + | null + ) { + const prom = new PromiEvent((resolve, reject) => { + this.onAny((eventName, eventData) => { + return prom.emit(eventName, eventData); + }); + const p = super.catch(onrejected); + p.then(resolve, reject); + }); + return prom; + } + + /** + * Creates a new resolved promievent. + * @returns A resolved promievent. + */ + static resolve(): PromiEvent; + /** + * Creates a new resolved promievent for the provided value. + * @param value A promise. + * @returns A promievent whose internal state matches the provided promise. + */ + static resolve(value: T | PromiseLike): PromiEvent; + static resolve(value?: T | PromiseLike) { + return new PromiEvent(resolve => { + resolve(value); + }); + } + + /** + * Used to immediately clear all event listeners on the instance and prevent + * any additional binding or emission from the Emitter. + * + * Once disposed no listeners can be bound to this emitter. + * + * Note: `dispose` is pre-bound to the `this`, making it possible to pass the + * method around detached from it's context. + */ + public dispose = () => { + if (!this.clearListeners) throw new Error("PromiEvent already disposed"); + + this.clearListeners(); + + // Ensure that once disposed no listeners can be bound to this emitter. + const fn = () => { + throw new Error("PromiEvent bound after dispose"); + }; + emitteryMethods + .filter(m => m !== "emit") + .forEach(methodName => { + Object.defineProperty(this, methodName, { + enumerable: false, + value: fn + }); + }); + }; +} + +interface PromiEvent + extends Promise, + Pick { + emittery: Emittery; +} + +export default PromiEvent; diff --git a/src/packages/utils/src/types/api.ts b/src/packages/utils/src/types/api.ts new file mode 100644 index 0000000000..c4405ffc15 --- /dev/null +++ b/src/packages/utils/src/types/api.ts @@ -0,0 +1,13 @@ +/** + * Base implementation for an API. + * All properties must be `async` callable or return a `Promise` + */ +class ApiBase { + readonly [index: string]: (...args: unknown[]) => Promise; +} + +/** + * Defines the interface for a API. + * All properties must be `async` callable or return a `Promise` + */ +export interface Api extends ApiBase {} diff --git a/src/packages/utils/src/types/connector.ts b/src/packages/utils/src/types/connector.ts new file mode 100644 index 0000000000..498bb94876 --- /dev/null +++ b/src/packages/utils/src/types/connector.ts @@ -0,0 +1,53 @@ +import { Provider } from "./provider"; +import { RecognizedString, WebSocket, HttpRequest } from "uWebSockets.js"; +import { Api } from "./api"; +import { KnownKeys } from "../types"; +import Emittery from "emittery"; + +/** + * Connects an arbitrary public chain provider to ganache-core + */ +export interface Connector< + ApiImplementation extends Api, + RequestFormat, + ResponseFormat +> extends Emittery.Typed { + provider: Provider; + + /** + * Parses a raw message into something that can be handled by `handle` + * @param message + */ + parse(message: Buffer): RequestFormat; + + /** + * Handles a parsed message + * @param payload + */ + handle: + | (( + payload: RequestFormat, + connection: HttpRequest + ) => Promise<{ value: ReturnType]> }>) + | (( + payload: RequestFormat[], + connection: HttpRequest + ) => Promise<{ value: ReturnType]>[] }>) + | (( + payload: RequestFormat, + connection: WebSocket + ) => Promise<{ value: ReturnType]> }>) + | (( + payload: RequestFormat[], + connection: WebSocket + ) => Promise<{ value: ReturnType]>[] }>); + + /** + * Formats the response (returned from `handle`) + * @param response + * @param payload + */ + format(result: ResponseFormat, payload: RequestFormat): RecognizedString; + + close(): void; +} diff --git a/src/packages/utils/src/types/index.ts b/src/packages/utils/src/types/index.ts new file mode 100644 index 0000000000..4e5c3e9163 --- /dev/null +++ b/src/packages/utils/src/types/index.ts @@ -0,0 +1,23 @@ +export * from "./connector"; +export * from "./provider"; +export * from "./api"; + +import { Api } from "./api"; + +export type KnownKeys = { + [K in keyof T]: string extends K ? never : number extends K ? never : K; +} extends { [_ in keyof T]: infer U } + ? U + : never; + +export type RequestType = (eventDetails: { + api: T; + method: KnownKeys; + params?: Parameters; +}) => ReturnType; + +declare global { + interface JSON { + parse(text: Buffer, reviver?: (key: any, value: any) => any): any; + } +} diff --git a/src/packages/utils/src/types/provider.ts b/src/packages/utils/src/types/provider.ts new file mode 100644 index 0000000000..09a872400e --- /dev/null +++ b/src/packages/utils/src/types/provider.ts @@ -0,0 +1,3 @@ +import { Api } from "./api"; + +export interface Provider {} diff --git a/src/packages/utils/src/utils/bigint-to-buffer.ts b/src/packages/utils/src/utils/bigint-to-buffer.ts new file mode 100644 index 0000000000..7670043227 --- /dev/null +++ b/src/packages/utils/src/utils/bigint-to-buffer.ts @@ -0,0 +1,54 @@ +import { uintToBuffer } from "./uint-to-buffer"; + +const MAX_UINT32 = 0xffffffffn; +const allocUnsafe = Buffer.allocUnsafe; + +let _bigIntToBuffer: (val: bigint) => Buffer; +/** + * Returns the number of bytes contained in this given `value`. + * @param value + */ +function bigIntByteLength(value: bigint) { + let length = 1; + while ((value >>= 8n)) length++; + return length; +} + +const MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER); +try { + const { toBufferBE } = require("bigint-buffer"); + + // force fallback if only `toBufferBE` is missing (this can happen if toBufferBE isn't polyfilled for the browser, + // which, at the time of this writing... it isn't) + if (!toBufferBE) throw new Error("Missing function `toBufferBE`!"); + + _bigIntToBuffer = (value: bigint) => { + if (value <= MAX_SAFE_INTEGER) { + return uintToBuffer(Number(value)); + } else { + const size = bigIntByteLength(value); + return toBufferBE(value, size); + } + }; +} catch (e) { + _bigIntToBuffer = (value: bigint): Buffer => { + if (value <= MAX_SAFE_INTEGER) { + // if this value can be handled as a JS number safely, convert it that way + return uintToBuffer(Number(value)); + } else { + let length = bigIntByteLength(value); + const buf = allocUnsafe(length); + do { + // process 1 byte at a time + buf[--length] = Number(value & 0xffffffffn); + value >>= 8n; + } while (length); + return buf; + } + }; +} + +/** + * Converts a bigint to a Buffer (Big Endian) + */ +export const bigIntToBuffer = _bigIntToBuffer; diff --git a/src/packages/utils/src/utils/constants.ts b/src/packages/utils/src/utils/constants.ts new file mode 100644 index 0000000000..a065b48e57 --- /dev/null +++ b/src/packages/utils/src/utils/constants.ts @@ -0,0 +1,12 @@ +import { Quantity } from "../things/json-rpc/json-rpc-quantity"; + +export const BUFFER_256_ZERO = Buffer.allocUnsafe(256).fill(0); +export const ACCOUNT_ZERO = BUFFER_256_ZERO.slice(0, 20); +export const BUFFER_EMPTY = Buffer.allocUnsafe(0); +export const BUFFER_ZERO = BUFFER_256_ZERO.slice(0, 1); +export const BUFFER_32_ZERO = BUFFER_256_ZERO.slice(0, 32); + +export const RPCQUANTITY_EMPTY = Quantity.from(BUFFER_EMPTY, true); +export const RPCQUANTITY_ZERO = Quantity.from(BUFFER_ZERO); +export const RPCQUANTITY_ONE = Quantity.from(1n); +export const WEI = 1000000000000000000n as const; diff --git a/src/packages/utils/src/utils/executor.ts b/src/packages/utils/src/utils/executor.ts new file mode 100644 index 0000000000..92fab8b1da --- /dev/null +++ b/src/packages/utils/src/utils/executor.ts @@ -0,0 +1,54 @@ +import { hasOwn } from "./has-own"; +import { KnownKeys, Api } from "../types"; +import { RequestCoordinator } from "./request-coordinator"; + +export class Executor { + #requestCoordinator: RequestCoordinator; + + /** + * The Executor handles execution of methods on the given API + */ + constructor(requestCoordinator: RequestCoordinator) { + this.#requestCoordinator = requestCoordinator; + } + + /** + * Executes the method with the given methodName on the API + * @param methodName The name of the JSON-RPC method to execute. + * @param params The params to pass to the JSON-RPC method. + */ + public execute>( + api: T, + methodName: M, + params: Parameters + ) { + // The methodName is user-entered data and can be all sorts of weird hackery + // Make sure we only accept what we expect to avoid headache and heartache + if (typeof methodName === "string") { + // Only allow executing our *own* methods. We allow: + // * functions added to the Instance by the class, e.g., + // class SomeClass { + // method = () => {} // api.hasOwnProperty("method") === true + // } + // * Or by the class' prototype: + // class SomeClass { + // method(){} // api.__proto__.hasOwnProperty("method") === true + // } + if ( + (hasOwn(api.__proto__, methodName) && methodName !== "constructor") || + hasOwn(api, methodName) + ) { + // cast methodName from `KnownKeys & string` back to KnownKeys so our return type isn't weird. + const fn = api[methodName as M]; + // just double check, in case a API breaks the rules and adds non-fns + // to their API interface. + if (typeof fn === "function") { + // queue up this method for actual execution: + return this.#requestCoordinator.queue(fn, api, params); + } + } + } + + throw new Error(`The method ${methodName} does not exist/is not available`); + } +} diff --git a/src/packages/utils/src/utils/has-own.ts b/src/packages/utils/src/utils/has-own.ts new file mode 100644 index 0000000000..5ba52c0fbd --- /dev/null +++ b/src/packages/utils/src/utils/has-own.ts @@ -0,0 +1,17 @@ +/** + * /** + * Determines whether an object has a property with the specified name. + * + * Safe for use on user-supplied data. + * + * @param obj The object that will be checked. + * @param v A property name. + * @returns `true` if the object has a property with the specified name, + * otherwise false. + */ +export const hasOwn: ( + obj: X, + prop: Y +) => obj is X extends Record + ? X & Required> + : never = {}.hasOwnProperty.call.bind({}.hasOwnProperty) as any; diff --git a/src/packages/utils/src/utils/heap.ts b/src/packages/utils/src/utils/heap.ts new file mode 100644 index 0000000000..e09d35f7d1 --- /dev/null +++ b/src/packages/utils/src/utils/heap.ts @@ -0,0 +1,210 @@ +type Comparator = (values: T[], a: number, b: number) => boolean; + +export class Heap { + public length: number = 0; + public array: T[] = []; + protected readonly less: Comparator; + + /** + * Creates a priority-queue heap where the highest priority element, + * as determined by the `less` function, is at the tip/root of the heap. + * To read the highest priority element without removing it call peek(). To + * read and remove the element call `shift()` + * @param size the size of the heap + * @param less the comparator function + */ + constructor(less: Comparator) { + this.less = less; + } + + public init(array: T[]) { + this.array = array; + const length = (this.length = array.length); + for (let i = ((length / 2) | 0) - 1; i >= 0; ) { + this.down(i--, length); + } + } + + /** + * Pushes a new element onto the heap + * @param value + */ + public push(value: T) { + const i = this.length++; + this.array[i] = value; + this.up(i); + } + + public size() { + return this.length; + } + + /** + * Return the current best element. Does not remove it + */ + public peek(): T { + return this.array[0]; + } + + public clear() { + this.length = this.array.length = 0; + } + + /** + * Removes and returns the element with the highest priority from the heap. + * The complexity is O(log n) where n = this.size(). + * @returns the element with the highest priority. returns `undefined` if + * there are no more elements in the heap. + */ + public shift(): T | undefined { + const length = this.length; + + // if we are empty or about to be empty... + if (length <= 1) { + if (length === 0) return; + const element = this.array[0]; + // finally, clear the array + this.clear(); + return element; + } + // otherwise... + + // remember the best element + const array = this.array; + const best = array[0]; + const newLength = (this.length = length - 1); + // put our last element at the start of the heap + array[0] = array[newLength]; + // then sort from the new first element to the second to last element + this.down(0, newLength); + return best; + } + + /** + * Removes the highest priority element from the queue, replacing it with + * the new element. This is equivalent to, but faster than, calling + * `replace(0, newValue);`. + * If you call this on an empty heap (`this.size() === 0`) you may find + * unexpected behavior. + * @param newValue + */ + public replaceBest(newValue: T) { + this.array[0] = newValue; + this.down(0, this.length); + } + + /** + * Replaces the element at position `i` with the `newValue`. If the element at + * position `i` doesn't exist, or if `i < 0` or `i > this.size()` you may + * find unexpected behavior. + * @param i + * @param newValue + */ + public replace(i: number, newValue: T) { + this.array[i] = newValue; + this.fix(i); + } + + /** + * Removes the element at position `i`. + * The complexity is O(log n) where n = this.size(). + * @param i the element to remove + */ + public remove(i: number) { + const newLength = --this.length; + if (newLength !== i) { + this.swap(i, newLength); + if (!this.down(i, newLength)) { + this.up(i); + } + } + } + + /** + * Removes the element with the highest priority from the heap + * The complexity is O(log n) where n = this.size(). + * @returns `true` when there are more elements in the queue, `false` when the + * last element was just removed. Calling `removeBest` when there are no more + * elements in the queue will return `true`. So don't do that. + */ + public removeBest() { + const array = this.array; + const length = this.length; + if (length === 1) { + // finally, clear the array + this.length = array.length = 0; + return false; + } + + const newLength = --this.length; + // put our last element at the start of the heap + array[0] = array[newLength]; + // then sort from the new first element to the second to last element + this.down(0, newLength); + return true; + } + + /** + * Re-establishes the heap ordering after the element at index `i` changes + * its value. Changing the value of the element at index `i` and then + * calling fix is equivalent to, but faster than, calling + * `remove(i); push(newValue);`. + * The complexity is O(log n) where n = this.size(). + * @param i + */ + public fix(i: number) { + if (!this.down(i, this.length)) { + this.up(i); + } + } + + private up(j: number) { + const less = this.less.bind(null, this.array); + for (let i: number; (i = ((j - 1) / 2) | 0), i !== j && less(j, i); j = i) { + this.swap(i, j); + } + } + + private down(i0: number, l: number): boolean { + const less = this.less.bind(null, this.array); + let i = i0; + for (let j1: number; (j1 = 2 * i + 1) < l; ) { + let j = j1; // left child + let j2 = j1 + 1; + if (j2 < l && less(j2, j1)) { + j = j2; // = 2 * i + 2 // right child + } + if (!less(j, i)) { + break; + } + this.swap(i, j); + i = j; + } + return i > i0; + } + + /** + * Swaps the elements in the heap + * @param i The first element + * @param j The second element + */ + private swap(i: number, j: number) { + const array = this.array; + const first = array[i]; + array[i] = array[j]; + array[j] = first; + } + + /** + * Heap initialization helper for when you only know of a single item for the + * heap. + * @param item + * @param less + */ + public static from(item: T, less: Comparator) { + const heap = new Heap(less); + heap.array = [item]; + heap.length = 1; + return heap; + } +} diff --git a/src/packages/utils/src/utils/index.ts b/src/packages/utils/src/utils/index.ts new file mode 100644 index 0000000000..e2ab466a84 --- /dev/null +++ b/src/packages/utils/src/utils/index.ts @@ -0,0 +1,8 @@ +export * from "./bigint-to-buffer"; +export * from "./executor"; +export * from "./heap"; +export * from "./request-coordinator"; +export * from "./unref"; +export * from "./has-own"; +export * from "./uint-to-buffer"; +export * from "./constants"; diff --git a/src/packages/utils/src/utils/request-coordinator.ts b/src/packages/utils/src/utils/request-coordinator.ts new file mode 100644 index 0000000000..b70f9409eb --- /dev/null +++ b/src/packages/utils/src/utils/request-coordinator.ts @@ -0,0 +1,102 @@ +const noop = () => {}; + +/** + * Responsible for managing global concurrent requests. + */ +export class RequestCoordinator { + /** + * The number of concurrent requests. Set to null for no limit. + */ + public limit: number; + + /** + * The pending requests. You can't do anything with this array. + */ + public readonly pending: ((...args: any) => Promise)[] = []; + + /** + * The number of tasks currently being processed. + */ + public runningTasks: number = 0; + #paused: boolean = true; + public get paused(): boolean { + return this.#paused; + } + + /** + * Promise-based FIFO queue. + * @param limit The number of requests that can be processed at a time. + * Default value is is no limit (`0`). + */ + constructor(limit: number) { + this.limit = limit; + } + + /** + * Pause processing. This will *not* cancel any promises that are currently + * running. + */ + public pause = () => { + this.#paused = true; + }; + + /** + * Resume processing. + */ + public resume = () => { + this.#paused = false; + this.#process(); + }; + + #process = () => { + // if we aren't paused and the number of things we're processing is under + // our limit and we have things to process: do it! + while ( + !this.paused && + this.pending.length > 0 && + (!this.limit || this.runningTasks < this.limit) + ) { + const current = this.pending.shift(); + this.runningTasks++; + current() + // By now, we've resolved the fn's `value` by sending it to the parent scope. + // But over here, we're also waiting for this fn's _value_ to settle _itself_ (it might be a promise) before + // continuing through the `pending` queue. Because we wait for it again here, it could potentially throw here, + // in which case we just need to catch it and throw the result away. We could probably use + // `Promise.allSettled([current()]).finally` to do this instead of the `current().catch(noop).finally`. /shrug + .catch(noop) + .finally(() => { + this.runningTasks--; + this.#process(); + }); + } + }; + + /** + * Insert a new function into the queue. + */ + public queue = unknown>( + fn: T, + thisArgument: any, + argumentsList: Parameters + ) => { + return new Promise<{ value: ReturnType }>((resolve, reject) => { + // const executor is `async` to force the return value into a Promise. + const executor = async () => { + try { + const value = Reflect.apply( + fn, + thisArgument, + argumentsList || [] + ) as ReturnType; + resolve({ value }); + return value; + } catch (e) { + reject(e); + } + }; + this.pending.push(executor); + this.#process(); + }); + }; +} diff --git a/src/packages/utils/src/utils/uint-to-buffer.ts b/src/packages/utils/src/utils/uint-to-buffer.ts new file mode 100644 index 0000000000..69288622be --- /dev/null +++ b/src/packages/utils/src/utils/uint-to-buffer.ts @@ -0,0 +1,179 @@ +const MAX_UINT32 = 0xffffffff; + +/** + * This is just Node's `Buffer.allocUnsafe`. I'm documenting it extra here to + * draw attention to it. It is much faster the `Buffer.alloc(size)` because it + * doesn't initialize its memory first. It's safe for us to use below because we + * guarantee that we will fill every octet ourselves. + * + * Allocates a new buffer of {size} octets, leaving memory not initialized, so + * the contents of the newly created Buffer are unknown and may contain + * sensitive data. + * + * @param {number} size count of octets to allocate + */ +const allocUnsafe = Buffer.allocUnsafe; + +/** + * Converts positive whole numbers that are 32 bits of fewer to a Buffer. Any + * more bits and who knows what will happen!?!1?! + * + * @param num A positive whole number less than 33 bits wide, i.e. a uint32. + * @returns an optimally sized buffer holding `num` in big-endian order (LSB is + * the _last_ value in the Buffer) + */ +function uint32ToBuf(num: number) { + let buf: Buffer; + + /** `lsb` holds the Least Significant *byte* of `num`. It *technically* holds + * all of `num`'s bytes but because of how UInt8Arrays (and thus Buffers) + * work, only the least significant byte of each value gets used. */ + const lsb = num; + + // shift the first 8 least signficant bits off current num, if it's non-zero + // our value contains at least 2 bytes! + if ((num >>>= 8)) { + /** `second` now holds the second most least significant byte in its + * "first" (right most) 8 bits */ + const second = num; + + // shift the next 8 least signficant bits off current num, if it's non-zero + // our value contains at least 3 bytes! + if ((num >>>= 8)) { + /** `third` now holds the third most least significant byte in its + * "first" (right most) 8 bits */ + const third = num; + if ((num >>>= 8)) { + // since we have all 4 bytes, create a 4 byte Buffer and fill it with + // our values! + buf = allocUnsafe(4); + // `num` here is just what is left after shifting off the 3 other bytes + // like we did above + buf[0] = num; + buf[1] = third; + buf[2] = second; + buf[3] = lsb; + } else { + // since we only have 3 bytes, create a 3 byte Buffer and fill it with + // our values! + buf = allocUnsafe(3); + buf[0] = third; + buf[1] = second; + buf[2] = lsb; + } + } else { + // since we only have 2 bytes, create a 2 byte Buffer and fill it with + // our values! + buf = allocUnsafe(2); + buf[0] = second; + buf[1] = lsb; + } + } else { + // We only have 1 byte, create a 1 byte Buffer and fill it with our only + // value, lsb! + buf = allocUnsafe(1); + buf[0] = lsb; + } + + // finally, return our optimally-sized Buffer! + return buf; +} + +/** + * Converts positive whole numbers less than or equal to + * `Number.MAX_SAFE_INTEGER` to a Buffer. If your value is less than 2**32 you + * should use `uint32ToBuf` instead. + * + * @param num A positive whole number <= `Number.MAX_SAFE_INTEGER` + * @returns an optimally sized buffer holding `num` in big-endian order (LSB is + * the _last_ value in the Buffer) + */ +function uintWideToBuf(num: number) { + // This function is similar to `uint32ToBuf`, but splits the number into its + // 32 lowest bits and its 32 highest bits. We have to do this because numeric + // Bitwise operations can only operate on 32 bit-wide values. + // There are some differences, but if you first grasp `uint32ToBuf`, you can + // handle this just fine. + + let buf: Buffer; + + /** If we are in this function we are probably > 32 bits wide, so we need to + * first convert this value to BigInt in order to shift off those high bits. + * Now that I'm documenting this, we could probably just subtract `2**32` from + * `num` to avoid the conversion overhead (BigInts are slower than numbers) */ + let hi = Number(BigInt(num) >> 32n); + + const hiLsb = hi; + let offset = 0; + + // the high bits determine the size of the Buffer, so we compute the high bits + // first + if ((hi >>>= 8)) { + const six = hi; + if ((hi >>>= 8)) { + const five = hi; + if ((hi >>>= 8)) { + buf = allocUnsafe(8); + buf[0] = hi; // msb + buf[1] = five; + buf[2] = six; + buf[3] = hiLsb; + offset = 7; + } else { + buf = allocUnsafe(7); + buf[0] = five; // msb + buf[1] = six; + buf[2] = hiLsb; + offset = 6; + } + } else { + buf = allocUnsafe(6); + buf[0] = six; // msb + buf[1] = hiLsb; + offset = 5; + } + } else { + buf = allocUnsafe(5); + buf[0] = hiLsb; // msb + offset = 4; + } + + // set the low bytes: + let lo = num & MAX_UINT32; + const lsb = lo; + if ((lo >>>= 8)) { + const two = lo; + if ((lo >>>= 8)) { + const one = lo; + buf[offset - 3] = lo >>>= 8; + buf[offset - 2] = one; + buf[offset - 1] = two; + buf[offset] = lsb; + } else { + buf[offset - 3] = 0; + buf[offset - 2] = 0; + buf[offset - 1] = two; + buf[offset] = lsb; + } + } else { + buf[offset - 3] = 0; + buf[offset - 2] = 0; + buf[offset - 1] = 0; + buf[offset] = lsb; + } + return buf; +} + +/** + * Converts a JavaScript number, treated as a Whole Number (0, 1, 2, 3, 4, ...) + * less than 64 bits wide, to a Buffer. + * + * Numbers that are negative, fractional, or greater than 64 bits wide will + * return very unexpected results. Numbers that are greater than + * `Number.MAX_SAFE_INTEGER` will return unexpected results. + * + * @param num A positive whole number <= `Number.MAX_SAFE_INTEGER` + */ +export function uintToBuffer(num: number) { + return num > MAX_UINT32 ? uintWideToBuf(num) : uint32ToBuf(num); +} diff --git a/src/packages/utils/src/utils/unref.ts b/src/packages/utils/src/utils/unref.ts new file mode 100644 index 0000000000..30d50e2b55 --- /dev/null +++ b/src/packages/utils/src/utils/unref.ts @@ -0,0 +1,16 @@ +/** + * In node, calling `unref(timer)` on a running timer ensures that the timer + * does not require that the Node.js event remain active. If there is no other + * activity keeping the event loop running, the process may exit before the + * timer's callback is invoked. + * @param timer + * @returns `true` if the timer could be `unref`ed, otherwise returns `false` + */ +export function unref(timer: NodeJS.Timeout | number): timer is NodeJS.Timeout { + if (typeof timer === "object" && typeof timer.unref === "function") { + timer.unref(); + return true; + } else { + return false; + } +} diff --git a/src/packages/utils/tests/utils.test.ts b/src/packages/utils/tests/utils.test.ts new file mode 100644 index 0000000000..b56cab343c --- /dev/null +++ b/src/packages/utils/tests/utils.test.ts @@ -0,0 +1,7 @@ +"use strict"; + +const utils = require(".."); + +describe("@ganache/utils", () => { + it("needs tests"); +}); diff --git a/src/packages/utils/tsconfig.json b/src/packages/utils/tsconfig.json new file mode 100644 index 0000000000..25d5c3cf7e --- /dev/null +++ b/src/packages/utils/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts"] +} diff --git a/test/DebugContract.sol b/test/DebugContract.sol deleted file mode 100644 index fdfcb91077..0000000000 --- a/test/DebugContract.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.4.2; - -// Changes to this file will make tests fail. -contract DebugContract { - uint public value = 5; - uint public otherValue = 5; - - function setValue(uint _val) { - value = _val; - otherValue += _val; - } -} diff --git a/test/EstimateGas.sol b/test/EstimateGas.sol deleted file mode 100644 index 6e087f5bca..0000000000 --- a/test/EstimateGas.sol +++ /dev/null @@ -1,89 +0,0 @@ -pragma solidity ^0.4.2; - -// From https://github.com/ethereumjs/testrpc/issues/58 -contract EstimateGas { - event Add(bytes32 name, bytes32 description, uint value, address owner); - - struct Test { - bytes32 name; - bytes32 description; - uint[] balances; - mapping(address => uint) owners; - } - - uint256 public x; - function reset() public { - x = 0; - } - function triggerRsclearRefund() public { - x = gasleft(); - reset(); - } - function triggerRselfdestructRefund() public { - selfdestruct(msg.sender); - } - function triggerAllRefunds() public { - triggerRsclearRefund(); - triggerRselfdestructRefund(); - } - - - // https://github.com/trufflesuite/ganache-cli/issues/294 - mapping (uint => uint) public uints; - // Sets the uints[1] slot to a value; - function store(uint _uint) public { uints[1] = _uint;} - function clear() public { delete uints[1]; } - - mapping(bytes32 => uint) index; - Test[] tests; - - function EstimateGas() { - tests.length++; - } - - function add(bytes32 _name, bytes32 _description, uint _value) returns(bool) { - if (index[_name] != 0) { - return false; - } - uint pos = tests.length++; - tests[pos].name = _name; - tests[pos].description = _description; - tests[pos].balances.length = 2; - tests[pos].balances[1] = _value; - tests[pos].owners[msg.sender] = 1; - index[_name] = pos; - Add(_name, _description, _value, msg.sender); - return true; - } - - function transfer(address _to, uint _value, bytes32 _name) returns(bool) { - uint pos = index[_name]; - if (pos == 0) { - return false; - } - - uint posFrom = tests[pos].owners[msg.sender]; - if (posFrom == 0) { - return false; - } - - if (tests[pos].balances[posFrom] < _value) { - return false; - } - - uint posTo = tests[pos].owners[_to]; - if (posTo == 0) { - uint posBal = tests[pos].balances.length++; - tests[pos].owners[_to] = posBal; - posTo = posBal; - } - - if (tests[pos].balances[posTo] + _value < tests[pos].balances[posTo]) { - return false; - } - tests[pos].balances[posFrom] -= _value; - tests[pos].balances[posTo] += _value; - - return true; - } -} diff --git a/test/Example.sol b/test/Example.sol deleted file mode 100644 index 87cf253013..0000000000 --- a/test/Example.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.4.2; - -contract Example { - uint public value; - - event ValueSet(uint); - - function Example() payable { - value = 5; - } - - function setValue(uint val) { - value = val; - ValueSet(val); - } -} diff --git a/test/LargeContract.sol b/test/LargeContract.sol deleted file mode 100644 index e85e677231..0000000000 --- a/test/LargeContract.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.4.2; - -// Changes to this file will make tests fail. -contract LargeContract { - function LargeFunction() public pure returns (string) { - return "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - } -} \ No newline at end of file diff --git a/test/Oracle.sol b/test/Oracle.sol deleted file mode 100644 index 6a357e9960..0000000000 --- a/test/Oracle.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.4.2; - -contract Oracle{ - bytes32 public blockhash0; - uint public lastBlock; - function Oracle(){ - blockhash0 = block.blockhash(0); - } - function currentBlock() returns (uint) { - return block.number; - } - function setCurrentBlock() { - lastBlock = block.number; - } -} diff --git a/test/Revert.sol b/test/Revert.sol deleted file mode 100644 index bb923510d4..0000000000 --- a/test/Revert.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.4.18; - -contract Revert { - uint public value; - - event ValueSet(uint); - - function alwaysReverts(uint val) public { - value = val; - ValueSet(val); - revert(); - } -} diff --git a/test/RuntimeError.sol b/test/RuntimeError.sol deleted file mode 100644 index cc390010de..0000000000 --- a/test/RuntimeError.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.4.2; - -// Changes to this file will make tests fail. -contract RuntimeError { - function error() { - for (uint i = 0; i < 3; ) { - i++; - } - throw; - } - - function errorWithMessage() { - for (uint i = 0; i < 3; ) { - i++; - } - revert("Message"); - } - - function success() { - - } -} diff --git a/test/accounts.js b/test/accounts.js deleted file mode 100644 index c00ec3b3bf..0000000000 --- a/test/accounts.js +++ /dev/null @@ -1,220 +0,0 @@ -var BN = require('bn.js'); -var Web3 = require('web3'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require('assert'); - -describe("Accounts", function() { - var expected_address = "0x604a95C9165Bc95aE016a5299dd7d400dDDBEa9A"; - var mnemonic = "into trim cross then helmet popular suit hammer cart shrug oval student"; - - it("should respect the BIP99 mnemonic", function(done) { - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - mnemonic: mnemonic, - })); - - web3.eth.getAccounts(function(err, accounts) { - if (err) return done(err); - - assert(accounts[0].toLowerCase(), expected_address.toLowerCase()); - done(); - }); - }); - - it("should lock all accounts when specified", function(done) { - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - mnemonic: mnemonic, - secure: true, - })); - - web3.eth.sendTransaction({ - from: expected_address, - to: "0x1234567890123456789012345678901234567890", // doesn't need to exist - value: web3.utils.toWei(new BN(1), "ether"), - gasLimit: 90000 - }, function(err, tx) { - if (!err) return done(new Error("We expected the account to be locked, which should throw an error when sending a transaction")); - assert(err.message.toLowerCase().indexOf("could not unlock signer account") >= 0, - 'Expected error message containing "could not unlock signer account" ' + - '(case insensitive check). Received the following error message, instead. ' + - `"${err.message}"`) - done(); - }); - }); - - it("should unlock specified accounts, in conjunction with --secure", function(done) { - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - mnemonic: mnemonic, - secure: true, - unlocked_accounts: [expected_address], - })); - - web3.eth.sendTransaction({ - from: expected_address, - to: "0x1234567890123456789012345678901234567890", // doesn't need to exist - value: web3.utils.toWei(new BN(1), "ether"), - gasLimit: 90000 - }, function(err, tx) { - if (err) return done(err); - // We should have no error here because the account is unlocked. - done(); - }); - }); - - it("should unlock specified accounts, in conjunction with --secure, using array indexes", function(done) { - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - mnemonic: mnemonic, - secure: true, - unlocked_accounts: [0] - })); - - web3.eth.sendTransaction({ - from: expected_address, - to: "0x1234567890123456789012345678901234567890", // doesn't need to exist - value: web3.utils.toWei(new BN(1), "ether"), - gasLimit: 90000 - }, function(err, tx) { - if (err) return done(err); - // We should have no error here because the account is unlocked. - done(); - }); - }); - - it("should unlock accounts even if private key isn't managed by the testrpc (impersonation)", function() { - var second_address = "0x1234567890123456789012345678901234567890"; - - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - mnemonic: mnemonic, - secure: true, - unlocked_accounts: [0, second_address], - })); - - // Set up: give second address some ether - return web3.eth.sendTransaction({ - from: expected_address, - to: second_address, - value: web3.utils.toWei(new BN(10), "ether"), - gasLimit: 90000 - }).then(() => { - // Now we should be able to send a transaction from second address without issue. - return web3.eth.sendTransaction({ - from: second_address, - to: expected_address, - value: web3.utils.toWei(new BN(5), "ether"), - gasLimit: 90000 - }); - }).then(tx => { - // And for the heck of it let's check the balance just to make sure it went through - return web3.eth.getBalance(second_address); - }).then(balance => { - var balanceInEther = web3.utils.fromWei(new BN(balance), "ether"); - - if (typeof balanceInEther === 'string') { - balanceInEther = parseFloat(balanceInEther); - } else { - balanceInEther.toNumber(); - } - - // Can't check the balance exactly. It cost some ether to send the transaction. - assert(balanceInEther > 4); - assert(balanceInEther < 5); - }); - }); - - it("errors when we try to sign a transaction from an account we're impersonating", function() { - var second_address = "0x1234567890123456789012345678901234567890"; - - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - mnemonic: mnemonic, - secure: true, - unlocked_accounts: [0, second_address], - })); - - return web3.eth.sign("some data", second_address) - .then(result => { - assert.fail("Expected an error while signing when not managing the private key") - }).catch(err => { - assert(err.message.toLowerCase().indexOf("cannot sign data; no private key") >= 0); - }); - }); - - it("should create a 2 accounts when passing an object to provider", function(done) { - - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - accounts: [ - { balance: '0x12' }, - { balance: '0x13' } - ], - })); - - web3.eth.getAccounts(function(err, result) { - if (err) return done(err); - assert(result.length, 2, "The number of accounts created should be 2"); - done(); - }) - }) - - - it("should create a 7 accounts when ", function(done) { - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - total_accounts: 7, - })); - - web3.eth.getAccounts(function(err, result) { - if (err) return done(err); - assert(result.length, 7, "The number of accounts created should be 7"); - done(); - }) - }) - - it("should respect the default_balance_ether option", function(done) { - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - default_balance_ether: 1.23456, - })); - - web3.eth.getAccounts(function(err, accounts) { - if (err) return done(err); - - function checkBalance(account) { - return new Promise(function(accept, reject) { - web3.eth.getBalance(accounts[0], function(err, balance) { - if (err) return reject(err); - - var balanceInEther = web3.utils.fromWei(balance, "Ether"); - - assert.equal(balanceInEther, 1.23456); - return accept(balance); - }); - }); - } - - accounts.reduce((promise, account, index) => { - var returnVal; - - if (promise) { - returnVal = promise.then(checkBalance(account)); - } else { - returnVal = checkBalance(account); - } - - if (index == accounts.length - 1) { - returnVal.then(done()) - .catch((err) => { done(err); }); - } - - return returnVal; - }, null); - - }); - }); - - -}); diff --git a/test/bad_input.js b/test/bad_input.js deleted file mode 100644 index cce46fff53..0000000000 --- a/test/bad_input.js +++ /dev/null @@ -1,176 +0,0 @@ -var Web3 = require('web3'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require('assert-match'); -var regex = require('assert-match/matchers').regex; - - -var tests = function(web3) { - var accounts; - - // The second request, after the first in each of these tests, - // informs us whether or not the provider crashed. - function secondRequest(callback) { - web3.eth.getAccounts(callback); - } - - describe("bad input", function() { - before(function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - it("recovers after to address that isn't a string", function(done) { - var provider = web3.currentProvider; - - provider.send({ - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [ - { - "value": "0x0", - "gas": "0xf4240", - "from": accounts[0], - // Buffers have been sent in the past - "to": { - "type": "Buffer", - "data": [ - // ... - ] - }, - "data": "0xe1fa8e84666f6f0000000000000000000000000000000000000000000000000000000000" - } - ], - "id": 2 - }, function() { - // Ignore any errors, but make sure we can make the second request - secondRequest(done); - }); - }); - - it("recovers after bad nonce (too high)", function(done) { - var provider = web3.currentProvider; - - var request = { - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [ - { - "value": "0x10000000", - "gas": "0xf4240", - "from": accounts[0], - "to": accounts[1], - "nonce": "0xffffffff", // too big nonce - } - ], - "id": 2 - } - - provider.send(request, function(err, result) { - // We're supposed to get an error the first time. Let's assert we get the right one. - // Note that if using the Ganache as a provider, err will be non-null when there's - // an error. However, when using it as a server it won't be. In both cases, however, - // result.error should be set with the same error message. We'll check for that. - assert(result.error.message.indexOf("the tx doesn't have the correct nonce. account has nonce of: 0 tx has nonce of: 4294967295") >= 0); - - delete request.params[0].nonce - provider.send(request, done) - }); - }); - - it("recovers after bad nonce (too low)", function(done) { - var provider = web3.currentProvider; - - var request = { - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [ - { - "value": "0x10000000", - "gas": "0xf4240", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x00", // too low nonce - } - ], - "id": 2 - } - - provider.send(request, function(err, result) { - // We're supposed to get an error the first time. Let's assert we get the right one. - // Note that if using the Ganache as a provider, err will be non-null when there's - // an error. However, when using it as a server it won't be. In both cases, however, - // result.error should be set with the same error message. We'll check for that. - assert(/the tx doesn't have the correct nonce. account has nonce of: 1 tx has nonce of: 0/.test(result.error.message), - `Expected incorrect nonce error, got '${result.error.message}', instead.`) - - delete request.params[0].nonce - provider.send(request, done) - }); - }); - - it("recovers after bad balance", function(done) { - web3.eth.getBalance(accounts[0], function(err, balance) { - if (err) return done(err); - - var provider = web3.currentProvider; - - var request = { - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [ - { - "value": "0x1000000000000000000000000000", - "gas": "0xf4240", - "from": accounts[0], - "to": accounts[1] - } - ], - "id": 2 - } - - provider.send(request, function(err, result) { - // We're supposed to get an error the first time. Let's assert we get the right one. - // Note that if using the Ganache as a provider, err will be non-null when there's - // an error. However, when using it as a server it won't be. In both cases, however, - // result.error should be set with the same error message. We'll check for that. - assert.deepEqual(result.error.message, regex(/sender doesn't have enough funds to send tx. The upfront cost is: \d+ and the sender's account only has: \d+/), - `Unexpected error message. Got ${result.error.message}.`); - - request.params[0].value = "0x5"; - provider.send(request, done) - }); - }) - }); - }) -}; - -describe("Provider:", function() { - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - })); - tests(web3); -}); - -describe("Server:", function(done) { - var web3 = new Web3(); - var port = 12345; - var server; - - before("Initialize Ganache server", function(done) { - server = Ganache.server({ - }); - server.listen(port, function() { - web3.setProvider(new Web3.providers.HttpProvider("http://localhost:" + port)); - done(); - }); - }); - - after("Shutdown server", function(done) { - server.close(done); - }); - - tests(web3); -}); diff --git a/test/block_tags.js b/test/block_tags.js deleted file mode 100644 index c5b4324ec0..0000000000 --- a/test/block_tags.js +++ /dev/null @@ -1,141 +0,0 @@ -var Web3 = require('web3'); -var utils = require('ethereumjs-util'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var fs = require("fs"); -var solc = require("solc"); -var async = require("async"); -var to = require("../lib/utils/to.js"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -var logger = { - log: function(msg) { /*noop*/ } -}; - -var source = fs.readFileSync("./test/Example.sol", {encoding: "utf8"}); -var result = solc.compile(source, 1); - -// Note: Certain properties of the following contract data are hardcoded to -// maintain repeatable tests. If you significantly change the solidity code, -// make sure to update the resulting contract data with the correct values. -var contract = { - solidity: source, - abi: result.contracts[":Example"].interface, - binary: "0x" + result.contracts[":Example"].bytecode, - position_of_value: "0x0000000000000000000000000000000000000000000000000000000000000000", - expected_default_value: 5, - call_data: { - gas: '0x2fefd8', - gasPrice: '0x01', // This is important, as passing it has exposed errors in the past. - to: null, // set by test - data: '0x3fa4f245' - }, - transaction_data: { - from: null, // set by test - gas: '0x2fefd8', - to: null, // set by test - data: '0x552410770000000000000000000000000000000000000000000000000000000000000019' // sets value to 25 (base 10) - } -}; - -describe("Block Tags", function() { - var accounts; - var web3 = new Web3(Ganache.provider()); - var contractAddress; - - var initial_block_number; - var initial = {}; - - before("Gather accounts", function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - before("Get initial block number", function(done) { - web3.eth.getBlockNumber(function(err, n) { - if (err) return done(err); - initial_block_number = to.number(n); - done(); - }); - }); - - before("Get initial balance and nonce", function(done) { - async.parallel({ - balance: web3.eth.getBalance.bind(web3.eth, accounts[0]), - nonce: web3.eth.getTransactionCount.bind(web3.eth, accounts[0]) - }, function(err, result) { - if (err) return done(err); - initial = result; - initial.nonce = to.number(initial.nonce); - done(); - }); - }); - - before("Make transaction that changes balance, nonce and code", function(done) { - web3.eth.sendTransaction({ - from: accounts[0], - data: contract.binary, - gas: 3141592 - }, function(err, tx) { - if (err) return done(err); - - web3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - - contractAddress = receipt.contractAddress; - done(); - }); - }); - }); - - it("should return the initial nonce at the previous block number", function(done) { - web3.eth.getTransactionCount(accounts[0], initial_block_number, function(err, nonce) { - if (err) return done(err); - assert.equal(nonce, initial.nonce); - - // Check that the nonce incremented with the block number, just to be sure. - web3.eth.getTransactionCount(accounts[0], initial_block_number + 1, function(err, nonce) { - if (err) return done(err); - assert.equal(nonce, initial.nonce + 1); - done(); - }); - }); - }); - - it("should return the initial balance at the previous block number", function(done) { - web3.eth.getBalance(accounts[0], initial_block_number, function(err, balance) { - if (err) return done(err); - assert.equal(balance, initial.balance); - - // Check that the balance incremented with the block number, just to be sure. - web3.eth.getBalance(accounts[0], initial_block_number + 1, function(err, balance) { - if (err) return done(err); - var initialBalanceInEther = parseFloat(web3.utils.fromWei(initial.balance, 'ether')); - var balanceInEther = parseFloat(web3.utils.fromWei(balance, 'ether')); - assert(balanceInEther < initialBalanceInEther); - done(); - }); - }); - }); - - it("should return the no code at the previous block number", function(done) { - web3.eth.getCode(contractAddress, initial_block_number, function(err, code) { - if (err) return done(err); - assert.equal(code, "0x"); - - // Check that the code incremented with the block number, just to be sure. - web3.eth.getCode(contractAddress, initial_block_number + 1, function(err, code) { - if (err) return done(err); - assert.notEqual(code, "0x"); - assert(code.length > 20); // Just because we don't know the actual code we're supposed to get back - done(); - }); - }); - }); -}); diff --git a/test/call.js b/test/call.js deleted file mode 100644 index e6b2bf7c7f..0000000000 --- a/test/call.js +++ /dev/null @@ -1,71 +0,0 @@ -var Web3 = require('web3'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var fs = require("fs"); -var path = require("path"); -var solc = require("solc"); -var to = require("../lib/utils/to.js"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -describe("eth_call", function() { - var web3 = new Web3(Ganache.provider({})); - var accounts; - var estimateGasContractData; - var estimateGasContractAbi; - var EstimateGasContract; - var estimateGasInstance; - var deploymentReceipt; - var source = fs.readFileSync(path.join(__dirname, "EstimateGas.sol"), "utf8"); - - before("get accounts", function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - before("compile source and deploy", function() { - this.timeout(10000); - var result = solc.compile({sources: {"EstimateGas.sol": source}}, 1); - - estimateGasContractData = "0x" + result.contracts["EstimateGas.sol:EstimateGas"].bytecode; - estimateGasContractAbi = JSON.parse(result.contracts["EstimateGas.sol:EstimateGas"].interface); - - EstimateGasContract = new web3.eth.Contract(estimateGasContractAbi); - return EstimateGasContract.deploy({data: estimateGasContractData}) - .send({from: accounts[0], gas: 3141592}) - .on('receipt', function (receipt) { - deploymentReceipt = receipt; - }) - .then(function(instance) { - // TODO: ugly workaround - not sure why this is necessary. - if (!instance._requestManager.provider) { - instance._requestManager.setProvider(web3.eth._provider); - } - estimateGasInstance = instance; - }); - }); - - it("should use the block gas limit if no gas limit is specified", function() { - // this call uses more than the default transaction gas limit and will - // therefore fail if the block gas limit isn't used for calls - return estimateGasInstance.methods.add(toBytes("Tim"), toBytes("A great guy"), 5) - .call({from: accounts[0]}) - .then(result => { - assert.equal(result, true) - }) - }) - - function toBytes(s) { - let bytes = Array.prototype.map.call(s, function(c) { - return c.codePointAt(0) - }) - - return to.hex(Buffer.from(bytes)) - } - -}); diff --git a/test/custom_gas_limit.js b/test/custom_gas_limit.js deleted file mode 100644 index 2d220d8d83..0000000000 --- a/test/custom_gas_limit.js +++ /dev/null @@ -1,23 +0,0 @@ -var Web3 = require('web3'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); - -describe("Custom Gas Limit", function() { - var web3; - - before("Init the Web3 provider", function(done){ - web3 = new Web3(); - web3.setProvider(Ganache.provider({ - gasLimit: 5000000 - })); - done(); - }); - - it("The block should show the correct custom Gas Limit", function(done) { - web3.eth.getBlock(0, function(err, block) { - if (err) return done(err); - assert.deepEqual(block.gasLimit, 5000000); - done(); - }); - }); -}); diff --git a/test/custom_gas_price.js b/test/custom_gas_price.js deleted file mode 100644 index a6078001f4..0000000000 --- a/test/custom_gas_price.js +++ /dev/null @@ -1,32 +0,0 @@ -var Web3 = require('web3'); -var utils = require('ethereumjs-util'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); - -var logger = { - log: function() {} -}; - -describe("Custom Gas Price", function() { - it("should return gas price of 0xf when specified as a decimal", function(done) { - var provider = Ganache.provider({gasPrice: 15, logger: logger}); - var web3 = new Web3(); - web3.setProvider(provider); - web3.eth.getGasPrice(function(err, result) { - if (err) return done(err); - assert.equal(parseFloat(result), 15); - done(); - }); - }); - - it("should return gas price of 0xf when specified as hex", function(done) { - var provider = Ganache.provider({gasPrice: 0xf, logger: logger}); - var web3 = new Web3(); - web3.setProvider(provider); - web3.eth.getGasPrice(function(err, result) { - if (err) return done(err); - assert.equal(parseFloat(result), 15); - done(); - }); - }); -}); diff --git a/test/debug.js b/test/debug.js deleted file mode 100644 index c463d2631b..0000000000 --- a/test/debug.js +++ /dev/null @@ -1,125 +0,0 @@ -var Web3 = require('web3'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var fs = require("fs"); -var path = require("path"); -var solc = require("solc"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -describe("Debug", function() { - var provider; - var web3 - var accounts; - var DebugContract; - var debugContract; - var source = fs.readFileSync(path.join(__dirname, "DebugContract.sol"), "utf8"); - var hashToTrace = null; - var expectedValueBeforeTrace = 1234; - - before("init web3", function() { - provider = Ganache.provider(); - web3 = new Web3(provider); - }); - - before("get accounts", function() { - return web3.eth.getAccounts().then(accs => { - accounts = accs; - }); - }); - - before("compile source", function() { - this.timeout(10000); - var result = solc.compile({sources: {"DebugContract.sol": source}}, 1); - - var code = "0x" + result.contracts["DebugContract.sol:DebugContract"].bytecode; - var abi = JSON.parse(result.contracts["DebugContract.sol:DebugContract"].interface); - - DebugContract = new web3.eth.Contract(abi); - DebugContract._code = code; - - return DebugContract.deploy({ data: code }).send({from: accounts[0], gas: 3141592}).then(instance => { - debugContract = instance; - - // TODO: ugly workaround - not sure why this is necessary. - if (!debugContract._requestManager.provider) { - debugContract._requestManager.setProvider(web3.eth._provider); - } - }); - }); - - before("set up transaction that should be traced", function() { - // This should execute immediately. - var setValueTx = debugContract.methods.setValue(26) - var tx; - return setValueTx.send({from: accounts[0], gas: 3141592}).then(result => { - // Check the value first to make sure it's 26 - tx = result; - return debugContract.methods.value().call({from: accounts[0], gas: 3141592}); - }).then(value => { - assert.equal(value, 26); - - // Set the hash to trace to the transaction we made, so we know preconditions - // are set correctly. - hashToTrace = tx.transactionHash; - }); - }); - - before("change state of contract to ensure trace doesn't overwrite data", function() { - // This should execute immediately. - return debugContract.methods.setValue(expectedValueBeforeTrace).send({from: accounts[0], gas: 3141592}).then(tx => { - // Make sure we set it right. - return debugContract.methods.value().call({from: accounts[0], gas: 3141592}) - }).then(value => { - // Now that it's 85, we can trace the transaction that set it to 26. - assert.equal(value, expectedValueBeforeTrace); - }); - }); - - it("should trace a successful transaction without changing state", function() { - // We want to trace the transaction that sets the value to 26 - return new Promise((accept, reject) => { - provider.send({ - jsonrpc: "2.0", - method: "debug_traceTransaction", - params: [hashToTrace, []], - id: new Date().getTime() - }, function(err, response) { - if (err) reject(err); - if (response.error) reject(response.error); - - var result = response.result; - - // To at least assert SOMETHING, let's assert the last opcode - assert(result.structLogs.length > 0); - - for (let op of result.structLogs) { - if (op.stack.length > 0) { - // check formatting of stack - // formatting was broken when updating to ethereumjs-vm v2.3.3 - assert.equal(op.stack[0].length, 64) - assert.notEqual(op.stack[0].substr(0, 2), '0x') - break - } - } - var lastop = result.structLogs[result.structLogs.length - 1]; - - assert.equal(lastop.op, "STOP"); - assert.equal(lastop.gasCost, 1); - assert.equal(lastop.pc, 145); - assert.equal(lastop.storage['0000000000000000000000000000000000000000000000000000000000000000'], '000000000000000000000000000000000000000000000000000000000000001a') - assert.equal(lastop.storage['0000000000000000000000000000000000000000000000000000000000000001'], '000000000000000000000000000000000000000000000000000000000000001f') - - accept(); - }); - }).then(() => { - // Now let's make sure rerunning this transaction trace didn't change state - return debugContract.methods.value().call({from: accounts[0], gas: 3141592}) - });then(value => { - // Did it change state? - assert.equal(value, expectedValueBeforeTrace); - }); - }); -}) diff --git a/test/ethereum.js b/test/ethereum.js deleted file mode 100644 index 55362d59e9..0000000000 --- a/test/ethereum.js +++ /dev/null @@ -1,20 +0,0 @@ -var Web3 = require('web3'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); - - -describe("Ethereum", function(done) { - var web3 = new Web3(); - var provider; - - before("Initialize the provider", function() { - provider = Ganache.provider(); - web3.setProvider(provider); - }); - - it("should get ethereum version (eth_protocolVersion)", function() { - return web3.eth.getProtocolVersion().then(result => { - assert.equal(result, "63", "Network Version should be 63"); - }) - }); -}); diff --git a/test/events.js b/test/events.js deleted file mode 100644 index a99d5ef4c2..0000000000 --- a/test/events.js +++ /dev/null @@ -1,291 +0,0 @@ -var Web3 = require('web3'); -var Web3WsProvider = require('web3-providers-ws'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require('assert'); -var solc = require("solc"); -var async = require("async"); -var util = require("util") - -var source = " \ -pragma solidity ^0.4.24; \ -contract EventTest { \ - event ExampleEvent(uint indexed first, uint indexed second); \ - \ - function triggerEvent(uint _first, uint _second) public { \ - emit ExampleEvent(_first, _second); \ - } \ -}" - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -var tests = function(web3, EventTest) { - var accounts; - var EventTest; - var instance; - - describe("events", function() { - before(function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - before(function(done) { - this.timeout(10000) - var result = solc.compile(source, 1); - - if (result.errors != null) { - done(result.errors[0]) - return - } - - var abi = JSON.parse(result.contracts[":EventTest"].interface); - EventTest = new web3.eth.Contract(abi); - EventTest._data = "0x" + result.contracts[":EventTest"].bytecode; - done(); - }); - - before(function() { - return EventTest.deploy({data: EventTest._data}) - .send({from: accounts[0], gas: 3141592}) - .then(contract => { - instance = contract; - - // TODO: ugly workaround - not sure why this is necessary. - if (!instance._requestManager.provider) { - instance._requestManager.setProvider(web3.eth._provider); - } - }); - }); - - it("should handle events properly via the data event handler", function(done) { - var expectedValue = 1; - - var event = instance.events.ExampleEvent({ filter: {first: expectedValue}}); - - var listener = function(result) { - assert.equal(result.returnValues.first, expectedValue); - done() - } - - event.once('data', listener); - event.once('error', (err) => done(err)); - - instance.methods.triggerEvent(1, 6) - .send({ from: accounts[0], gas: 3141592 }) - .catch(err => { cleanup(err); }) - }); - - // NOTE! This test relies on the events triggered in the tests above. - it("grabs events in the past", function(done) { - var expectedValue = 2; - - var event = instance.events.ExampleEvent({filter: {first: expectedValue}, fromBlock: 0}); - - var listener = function(result) { - assert.equal(result.returnValues.first, expectedValue) - done(); - } - - var errHandler = (err) => { cleanup(err) }; - event.once('data', listener); - event.once('error', errHandler); - - instance.methods.triggerEvent(2, 6) - .send({ from: accounts[0], gas: 3141592 }) - .catch(err => { cleanup(err); }) - }); - - // NOTE! This test relies on the events triggered in the tests above. - it("accepts an array of topics as a filter", function(done) { - var expectedValueA = 3; - var expectedValueB = 4; - var expectedValue = expectedValueA; - - var event = instance.events.ExampleEvent({filter: {first: [expectedValueA, expectedValueB]}, fromBlock: 0}); - - var waitingFor = {} - waitingFor[expectedValueA] = true - waitingFor[expectedValueB] = true - - var listener = function(result) { - assert(waitingFor.hasOwnProperty(result.returnValues.first)) - delete waitingFor[result.returnValues.first] - - if (Object.keys(waitingFor).length == 0) { - event.removeAllListeners() - done() - } - } - - event.on('data', listener); - - event.once('error', (err) => { - event.removeAllListeners() - done(err) - }); - - instance.methods.triggerEvent(expectedValueA, 6) - .send({ from: accounts[0], gas: 3141592 }) - .then((result) => { - return instance.methods.triggerEvent(expectedValueB, 7) - .send({ from: accounts[0], gas: 3141592 }) - }) - }); - - it("only returns logs for the expected address", function(done) { - var expectedValue = 1; - var event; - - EventTest.deploy({ data: EventTest._data }) - .send({ from: accounts[0], gas: 3141592 }) - .then(newInstance => { - // TODO: ugly workaround - not sure why this is necessary. - if (!newInstance._requestManager.provider) { - newInstance._requestManager.setProvider(web3.eth._provider); - } - - var event = newInstance.events.ExampleEvent({ filter: { first: expectedValue }, fromBlock: 0 }); - - event.on('data', function (result) { - assert(result.returnValues.first == expectedValue) - //event.removeAllListeners() - done(); - }); - - instance.methods.triggerEvent(5, 6) - .send({ from: accounts[0], gas: 3141592 }).then(() => { - newInstance.methods.triggerEvent(expectedValue, 6) - .send({ from: accounts[0], gas: 3141592 }) - }); - }); - - }); - - it("always returns a change for every new block subscription when instamining", function (done) { - var provider = web3.currentProvider; - - provider.send({ - jsonrpc: "2.0", - method: "eth_subscribe", - params: ['newHeads'], - id: new Date().getTime() - }, function (err, result) { - if (err) return done(err); - let filter_id = result.result; - - let listener = function (err, result) { - if(result == undefined) { - // If there's only one argument, it's the result, not an error - result = err; - } else if (err) { - return done(err); - } - let first_changes = result.params.result.hash; - assert.equal(first_changes.length, 66); // Ensure we have a hash - provider.removeAllListeners('data') - done(); - } - - // can't use `once` here because Web3WsProvider only has `on` :-( - provider.on('data', listener); - - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "evm_mine", - id: new Date().getTime() - }, function (err) { - if (err) done(err); - }) - }) - }); - - // NOTE! This test relies on the events triggered in the tests above. - it("ensures topics are respected in past events, using `event.get()` (exclusive)", function(done) { - var unexpectedValue = 1337; - var event = instance.events.ExampleEvent({filter: {first: unexpectedValue}, fromBlock: 0}); - - // There should be no logs because we provided a different number. - var listener = function(result) { - assert.fail('Event should not have fired'); - }; - - event.once('data', listener); - - instance.methods.triggerEvent(6, 6) - .send({ from: accounts[0], gas: 3141592 }) - .then(() => { - // have to finish somehow... - setTimeout(() => { - event.removeAllListeners() - done(); - }, 250) - }) - }); - - // TODO: web3 1.0 drops fromBlock on a subscription request - stop skipping this when that is fixed - it.skip("will not fire if logs are requested when fromBlock doesn't exist", function(done) { - var event = instance.events.ExampleEvent({fromBlock: 100000}); - - // fromBlock doesn't exist, hence no logs - var listener = function(result) { - assert.fail('Event should not have fired'); - }; - - event.on('data', listener); - - instance.methods.triggerEvent(8, 6) - .send({ from: accounts[0], gas: 3141592 }) - .then(() => { - // have to finish somehow... - setTimeout(() => { - event.removeAllListeners - done(); - }, 250) - }) - }); - }) -}; - -var logger = { - log: function(message) { - //console.log(message); - } -}; - -describe("Provider:", function() { - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - logger: logger - })); - tests(web3); -}); - -describe("Server:", function(done) { - var web3 = new Web3(); - var port = 12345; - var server; - - before("Initialize Ganache server", function(done) { - server = Ganache.server({ - logger: logger, - ws: true - }); - server.listen(port, function() { - web3.setProvider(new Web3WsProvider("ws://localhost:" + port)); - done(); - }); - }); - - tests(web3); - - after("Shutdown server", function(done) { - web3._provider.connection.close() - server.close(done); - }); - -}); diff --git a/test/forking.js b/test/forking.js deleted file mode 100644 index 643049dc0e..0000000000 --- a/test/forking.js +++ /dev/null @@ -1,630 +0,0 @@ -var Web3 = require('web3'); -var Web3WsProvider = require('web3-providers-ws'); -var utils = require('ethereumjs-util'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var fs = require("fs"); -var solc = require("solc"); -var to = require("../lib/utils/to.js"); -var async = require("async"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -var logger = { - log: function(msg) { /*console.log(msg)*/ } -}; - -/** - * NOTE: Naming in these tests is a bit confusing. Here, the "main chain" - * is the main chain the tests interact with; and the "forked chain" is the - * chain that _was forked_. This is in contrast to general naming, where the - * main chain represents the main chain to be forked (like the Ethereum live - * network) and the fork chaing being "the fork". - */ - -describe("Forking", function() { - var contract; - var contractAddress; - var secondContractAddress; // used sparingly - var forkedServer; - var mainAccounts; - var forkedAccounts; - - var initialFallbackAccountState = {}; - - var forkedWeb3 = new Web3(); - var mainWeb3 = new Web3(); - - var forkedTargetUrl = "ws://localhost:21345"; - var forkBlockNumber; - - var initialDeployTransactionHash; - - before("set up test data", function() { - this.timeout(10000) - var source = fs.readFileSync("./test/Example.sol", {encoding: "utf8"}); - var result = solc.compile(source, 1); - - // Note: Certain properties of the following contract data are hardcoded to - // maintain repeatable tests. If you significantly change the solidity code, - // make sure to update the resulting contract data with the correct values. - contract = { - solidity: source, - abi: result.contracts[":Example"].interface, - binary: "0x" + result.contracts[":Example"].bytecode, - position_of_value: "0x0000000000000000000000000000000000000000000000000000000000000000", - expected_default_value: 5, - call_data: { - gas: '0x2fefd8', - gasPrice: '0x01', // This is important, as passing it has exposed errors in the past. - to: null, // set by test - data: '0x3fa4f245' - }, - transaction_data: { - from: null, // set by test - gas: '0x2fefd8', - to: null, // set by test - data: '0x552410770000000000000000000000000000000000000000000000000000000000000019' // sets value to 25 (base 10) - } - }; - }); - - before("Initialize Fallback Ganache server", function(done) { - this.timeout(10000) - forkedServer = Ganache.server({ - // Do not change seed. Determinism matters for these tests. - seed: "let's make this deterministic", - ws: true, - logger: logger - }); - - forkedServer.listen(21345, function(err) { - if (err) return done(err); - done(); - }); - }); - - before("set forkedWeb3 provider", function(done) { - forkedWeb3.setProvider(new Web3WsProvider(forkedTargetUrl)); - done(); - }); - - before("Gather forked accounts", function(done) { - this.timeout(5000) - forkedWeb3.eth.getAccounts(function(err, f) { - if (err) return done(err); - forkedAccounts = f; - done(); - }); - }); - - before("Deploy initial contracts", function(done) { - forkedWeb3.eth.sendTransaction({ - from: forkedAccounts[0], - data: contract.binary, - gas: 3141592 - }, function(err, tx) { - if (err) { return done(err); } - - // Save this for a later test. - initialDeployTransactionHash = tx; - - forkedWeb3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - - contractAddress = receipt.contractAddress; - - forkedWeb3.eth.getCode(contractAddress, function(err, code) { - if (err) return done(err); - - // Ensure there's *something* there. - assert.notEqual(code, null); - assert.notEqual(code, "0x"); - assert.notEqual(code, "0x0"); - - // Deploy a second one, which we won't use often. - forkedWeb3.eth.sendTransaction({ - from: forkedAccounts[0], - data: contract.binary, - gas: 3141592 - }, function(err, tx) { - if (err) { return done(err); } - forkedWeb3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - - secondContractAddress = receipt.contractAddress; - done(); - }); - }); - }) - }); - }); - }); - - before("Make a transaction on the forked chain that produces a log", function(done) { - this.timeout(10000) - - var forkedExample = new forkedWeb3.eth.Contract(JSON.parse(contract.abi), contractAddress); - - // TODO: ugly workaround - not sure why this is necessary. - if (!forkedExample._requestManager.provider) { - forkedExample._requestManager.setProvider(forkedWeb3.eth._provider); - } - - var interval; - - var event = forkedExample.events.ValueSet({}); - - event.once('data', function(logs) { - done() - }); - - forkedExample.methods.setValue(7).send({from: forkedAccounts[0]}, function(err, tx) { - if (err) return done(err); - }); - }); - - before("Get initial balance and nonce", function(done) { - async.parallel({ - balance: forkedWeb3.eth.getBalance.bind(forkedWeb3.eth, forkedAccounts[0]), - nonce: forkedWeb3.eth.getTransactionCount.bind(forkedWeb3.eth, forkedAccounts[0]) - }, function(err, result) { - if (err) return done(err); - initialFallbackAccountState = result; - initialFallbackAccountState.nonce = to.number(initialFallbackAccountState.nonce); - done(); - }); - }); - - before("Set main web3 provider, forking from forked chain at this point", function(done) { - mainWeb3.setProvider(Ganache.provider({ - fork: forkedTargetUrl.replace('ws', 'http'), - logger, - verbose: true, - - // Do not change seed. Determinism matters for these tests. - seed: "a different seed" - })); - - forkedWeb3.eth.getBlockNumber(function(err, number) { - if (err) return done(err); - forkBlockNumber = number; - done(); - }); - }); - - before("Gather main accounts", function(done) { - this.timeout(5000) - mainWeb3.eth.getAccounts(function(err, m) { - if (err) return done(err); - mainAccounts = m; - done(); - }); - }); - - it("should fetch a contract from the forked provider via the main provider", function(done) { - mainWeb3.eth.getCode(contractAddress, function(err, mainCode) { - if (err) return done(err); - - // Ensure there's *something* there. - assert.notEqual(mainCode, null); - assert.notEqual(mainCode, "0x"); - assert.notEqual(mainCode, "0x0"); - - // Now make sure it matches exactly. - forkedWeb3.eth.getCode(contractAddress, function(err, forkedCode) { - if (err) return done(err); - - assert.equal(mainCode, forkedCode); - done(); - }); - }); - }); - - it("should be able to get the balance of an address in the forked provider via the main provider", function(done) { - // Assert preconditions - var first_forked_account = forkedAccounts[0]; - assert(mainAccounts.indexOf(first_forked_account) < 0); - - // Now for the real test: Get the balance of a forked account through the main provider. - mainWeb3.eth.getBalance(first_forked_account, function(err, balance) { - if (err) return done(err); - - // We don't assert the exact balance as transactions cost eth - assert(balance > 999999); - done(); - }); - }); - - it("should be able to get storage values on the forked provider via the main provider", function(done) { - mainWeb3.eth.getStorageAt(contractAddress, contract.position_of_value, function(err, result) { - if (err) return done(err); - assert.equal(mainWeb3.utils.hexToNumber(result), 7); - done(); - }); - }); - - it("should be able to execute calls against a contract on the forked provider via the main provider", function(done) { - var example = new mainWeb3.eth.Contract(JSON.parse(contract.abi), contractAddress); - - // TODO: ugly workaround - not sure why this is necessary. - if (!example._requestManager.provider) { - example._requestManager.setProvider(web3.eth._provider); - } - - example.methods.value().call({from: mainAccounts[0]}, function(err, result){ - if (err) return done(err); - assert.equal(mainWeb3.utils.hexToNumber(result), 7); - - // Make the call again to ensure caches updated and the call still works. - example.methods.value().call({from: mainAccounts[0]}, function(err, result){ - if (err) return done(err); - assert.equal(mainWeb3.utils.hexToNumber(result), 7); - done(err); - }); - }); - }); - - it("should be able to make a transaction on the main provider while not transacting on the forked provider", function(done) { - var example = new mainWeb3.eth.Contract(JSON.parse(contract.abi), contractAddress); - - // TODO: ugly workaround - not sure why this is necessary. - if (!example._requestManager.provider) { - example._requestManager.setProvider(web3.eth._provider); - } - - var forkedExample = new forkedWeb3.eth.Contract(JSON.parse(contract.abi), contractAddress); - - // TODO: ugly workaround - not sure why this is necessary. - if (!forkedExample._requestManager.provider) { - forkedExample._requestManager.setProvider(forkedWeb3.eth._provider); - } - - example.methods.setValue(25).send({from: mainAccounts[0]}, function(err) { - if (err) return done(err); - - // It insta-mines, so we can make a call directly after. - example.methods.value().call({from: mainAccounts[0]}, function(err, result) { - if (err) return done(err); - assert.equal(mainWeb3.utils.hexToNumber(result), 25); - - // Now call back to the forked to ensure it's value stayed 5 - forkedExample.methods.value().call({from: forkedAccounts[0]}, function(err, result) { - if (err) return done(err); - assert.equal(forkedWeb3.utils.hexToNumber(result), 7); - done(); - }) - }); - }); - }); - - it("should ignore continued transactions on the forked blockchain by pegging the forked block number", function(done) { - // In this test, we're going to use the second contract address that we haven't - // used previously. This ensures the data hasn't been cached on the main web3 trie - // yet, and it will require it forked to the forked provider at a specific block. - // If that block handling is done improperly, this should fail. - - var example = new mainWeb3.eth.Contract(JSON.parse(contract.abi), secondContractAddress); - - // TODO: ugly workaround - not sure why this is necessary. - if (!example._requestManager.provider) { - example._requestManager.setProvider(web3.eth._provider); - } - - var forkedExample = new forkedWeb3.eth.Contract(JSON.parse(contract.abi), secondContractAddress); - - // TODO: ugly workaround - not sure why this is necessary. - if (!forkedExample._requestManager.provider) { - forkedExample._requestManager.setProvider(forkedWeb3.eth._provider); - } - - // This transaction happens entirely on the forked chain after forking. - // It should be ignored by the main chain. - forkedExample.methods.setValue(800).send({from: forkedAccounts[0]}, function(err, result) { - if (err) return done(err); - // Let's assert the value was set correctly. - forkedExample.methods.value().call({from: forkedAccounts[0]}, function(err, result) { - if (err) return done(err); - assert.equal(forkedWeb3.utils.hexToNumber(result), 800); - - // Now lets check the value on the main chain. It shouldn't be 800. - example.methods.value().call({from: mainAccounts[0]}, function(err, result) { - if (err) return done(err); - - assert.equal(mainWeb3.utils.hexToNumber(result), 5); - done(); - }) - }) - }); - }); - - it("should maintain a block number that includes new blocks PLUS the existing chain", function(done) { - // Note: The main provider should be at block 5 at this test. Reasoning: - // - The forked chain has an initial block, which is block 0. - // - The forked chain performed a transaction that produced a log, resulting in block 1. - // - The forked chain had two transactions initially, resulting blocks 2 and 3. - // - The main chain forked from there, creating its own initial block, block 4. - // - Then the main chain performed a transaction, putting it at block 5. - - mainWeb3.eth.getBlockNumber(function(err, result) { - if (err) return done(err); - - assert.equal(mainWeb3.utils.hexToNumber(result), 5); - - // Now lets get a block that exists on the forked chain. - mainWeb3.eth.getBlock(0, function(err, mainBlock) { - if (err) return done(err); - - // And compare it to the forked chain's block - forkedWeb3.eth.getBlock(0, function(err, forkedBlock) { - if (err) return done(err); - - // Block hashes should be the same. - assert.equal(mainBlock.hash, forkedBlock.hash); - - // Now make sure we can get the block by hash as well. - mainWeb3.eth.getBlock(mainBlock.hash, function(err, mainBlockByHash) { - if (err) return done(err); - - assert.equal(mainBlock.hash, mainBlockByHash.hash); - done(); - }); - }); - }); - }); - }); - - it("should have a genesis block whose parent is the last block from the forked provider", function(done) { - forkedWeb3.eth.getBlock(forkBlockNumber, function(err, forkedBlock) { - if (err) return done(err); - - var parentHash = forkedBlock.hash; - - var mainGenesisNumber = mainWeb3.utils.hexToNumber(forkBlockNumber) + 1; - mainWeb3.eth.getBlock(mainGenesisNumber, function(err, mainGenesis) { - if (err) return done(err); - - assert.equal(mainGenesis.parentHash, parentHash); - done(); - }) - }); - }); - - // Note: This test also puts a new contract on the forked chain, which is a good test. - it("should represent the block number correctly in the Oracle contract (oracle.blockhash0), providing forked block hash and number", function() { - this.timeout(10000) - var oracleSol = fs.readFileSync("./test/Oracle.sol", {encoding: "utf8"}); - var solcResult = solc.compile(oracleSol); - var oracleOutput = solcResult.contracts[":Oracle"]; - - return new mainWeb3.eth.Contract(JSON.parse(oracleOutput.interface)) - .deploy({ data: oracleOutput.bytecode }) - .send({ from: mainAccounts[0], gas: 3141592 }) - .then(function(oracle){ - // TODO: ugly workaround - not sure why this is necessary. - if (!oracle._requestManager.provider) { - oracle._requestManager.setProvider(mainWeb3.eth._provider); - } - return mainWeb3.eth.getBlock(0).then(function(block){ - return oracle.methods.blockhash0().call() - .then(function(blockhash) { - assert.equal(blockhash, block.hash); - // Now check the block number. - return mainWeb3.eth.getBlockNumber() - }) - }).then(function(expected_number) { - return oracle.methods.currentBlock().call() - .then(function(number) { - assert.equal(number, expected_number + 1); - return oracle.methods.setCurrentBlock().send({from: mainAccounts[0], gas: 3141592}) - }).then(function(tx) { - return oracle.methods.lastBlock().call({from: mainAccounts[0]}) - }).then(function(val) { - assert.equal(to.number(val), expected_number + 1); - }); - }); - }); - }); - - // TODO - it("should be able to get logs across the fork boundary", function(done) { - this.timeout(30000) - - var example = new mainWeb3.eth.Contract(JSON.parse(contract.abi), contractAddress); - - // TODO: ugly workaround - not sure why this is necessary. - if (!example._requestManager.provider) { - example._requestManager.setProvider(web3.eth._provider); - } - - var event = example.events.ValueSet({fromBlock: 0, toBlock: "latest"}); - - var callcount = 0 - event.on('data', function(log) { - callcount++ - if (callcount == 2) { - event.removeAllListeners() - done() - } - }); - }); - - it("should return the correct nonce based on block number", function(done) { - // Note for the first two requests, we choose the block numbers 1 before and after the fork to - // ensure we're pulling data off the correct provider in both cases. - async.parallel({ - nonceBeforeFork: mainWeb3.eth.getTransactionCount.bind(mainWeb3.eth, forkedAccounts[0], forkBlockNumber - 1), - nonceAtFork: mainWeb3.eth.getTransactionCount.bind(mainWeb3.eth, forkedAccounts[0], forkBlockNumber + 1), - nonceLatestMain: mainWeb3.eth.getTransactionCount.bind(mainWeb3.eth, forkedAccounts[0], "latest"), - nonceLatestFallback: forkedWeb3.eth.getTransactionCount.bind(forkedWeb3.eth, forkedAccounts[0], "latest") - }, function(err, results) { - if (err) return done(err); - - var nonceBeforeFork = results.nonceBeforeFork; - var nonceAtFork = results.nonceAtFork; - var nonceLatestMain = results.nonceLatestMain; - var nonceLatestFallback = results.nonceLatestFallback; - - // First ensure our nonces for the block before the fork - // Note that we're asking for the block *before* the forked block, - // which automatically means we sacrifice a transaction (i.e., one nonce value) - assert.equal(nonceBeforeFork, initialFallbackAccountState.nonce - 1); - - // Now check at the fork. We should expect our initial state. - assert.equal(nonceAtFork, initialFallbackAccountState.nonce); - - // Make sure the main web3 provider didn't alter the state of the forked account. - // This means the nonce should stay the same. - assert.equal(nonceLatestMain, initialFallbackAccountState.nonce); - - // And since we made one additional transaction with this account on the forked - // provider AFTER the fork, it's nonce should be one ahead, and the main provider's - // nonce for that address shouldn't acknowledge it. - assert.equal(nonceLatestFallback, nonceLatestMain + 1); - - done(); - }); - }); - - it("should return the correct balance based on block number", function(done) { - // Note for the first two requests, we choose the block numbers 1 before and after the fork to - // ensure we're pulling data off the correct provider in both cases. - async.parallel({ - balanceBeforeFork: mainWeb3.eth.getBalance.bind(mainWeb3.eth, forkedAccounts[0], forkBlockNumber - 1), - balanceAfterFork: mainWeb3.eth.getBalance.bind(mainWeb3.eth, forkedAccounts[0], forkBlockNumber + 1), - balanceLatestMain: mainWeb3.eth.getBalance.bind(mainWeb3.eth, forkedAccounts[0], "latest"), - balanceLatestFallback: forkedWeb3.eth.getBalance.bind(forkedWeb3.eth, forkedAccounts[0], "latest") - }, function(err, results) { - if (err) return done(err); - - var balanceBeforeFork = mainWeb3.utils.toBN(results.balanceBeforeFork); - var balanceAfterFork = mainWeb3.utils.toBN(results.balanceAfterFork); - var balanceLatestMain = mainWeb3.utils.toBN(results.balanceLatestMain); - var balanceLatestFallback = mainWeb3.utils.toBN(results.balanceLatestFallback); - - // First ensure our balances for the block before the fork - // We do this by simply ensuring the balance has decreased since exact values - // are hard to assert in this case. - assert(balanceBeforeFork.gt(balanceAfterFork)); - - // Make sure it's not substantially larger. it should only be larger by a small - // amount (<2%). This assertion was added since forked balances were previously - // incorrectly being converted between decimal and hex - assert(balanceBeforeFork.muln(0.95).lt(balanceAfterFork)); - - // Since the forked provider had once extra transaction for this account, - // it should have a lower balance, and the main provider shouldn't acknowledge - // that transaction. - assert(balanceLatestMain.gt(balanceLatestFallback)); - - // Make sure it's not substantially larger. it should only be larger by a small - // amount (<2%). This assertion was added since forked balances were previously - // incorrectly being converted between decimal and hex - assert(balanceLatestMain.muln(0.95).lt(balanceLatestFallback)); - - done(); - }); - }); - - it("should return the correct code based on block number", function(done) { - // This one is simpler than the previous two. Either the code exists or doesn't. - async.parallel({ - codeEarliest: mainWeb3.eth.getCode.bind(mainWeb3.eth, contractAddress, "earliest"), - codeAfterFork: mainWeb3.eth.getCode.bind(mainWeb3.eth, contractAddress, forkBlockNumber + 1), - codeLatest: mainWeb3.eth.getCode.bind(mainWeb3.eth, contractAddress, "latest") - }, function(err, results) { - if (err) return done(err); - - var codeEarliest = results.codeEarliest; - var codeAfterFork = results.codeAfterFork; - var codeLatest = results.codeLatest; - - // There should be no code initially. - assert.equal(to.number(codeEarliest), 0) - - // Arbitrary length check since we can't assert the exact value - assert(codeAfterFork.length > 20); - assert(codeLatest.length > 20); - - // These should be the same since code can't change. - assert.equal(codeAfterFork, codeLatest); - - done(); - }) - }); - - it("should return transactions for blocks requested before the fork", function(done) { - forkedWeb3.eth.getTransactionReceipt(initialDeployTransactionHash, function(err, receipt) { - if (err) return done(err); - - forkedWeb3.eth.getBlock(receipt.blockNumber, true, function(err, referenceBlock) { - if (err) return done(err); - - mainWeb3.eth.getBlock(receipt.blockNumber, true, function(err, forkedBlock) { - if (err) return done(err); - - assert.equal(forkedBlock.transactions.length, referenceBlock.transactions.length) - assert.deepEqual(forkedBlock.transactions, referenceBlock.transactions); - done(); - }); - }); - }); - }); - - it("should return a transaction for transactions made before the fork", function(done) { - forkedWeb3.eth.getTransaction(initialDeployTransactionHash, function(err, referenceTransaction) { - if (err) return done(err); - - mainWeb3.eth.getTransaction(initialDeployTransactionHash, function(err, forkedTransaction) { - if (err) return done(err); - - assert.deepEqual(referenceTransaction, forkedTransaction); - done(); - }); - }); - }); - - it("should return a transaction receipt for transactions made before the fork", function(done) { - forkedWeb3.eth.getTransactionReceipt(initialDeployTransactionHash, function(err, referenceReceipt) { - if (err) return done(err); - assert.deepEqual(referenceReceipt.transactionHash, initialDeployTransactionHash) - - mainWeb3.eth.getTransactionReceipt(initialDeployTransactionHash, function(err, forkedReceipt) { - if (err) return done(err); - - assert.deepEqual(forkedReceipt.transactionHash, initialDeployTransactionHash) - assert.deepEqual(referenceReceipt, forkedReceipt); - done(); - }); - }); - }) - - it("should return the same network version as the chain it forked from", function(done) { - forkedWeb3.eth.net.getId(function(err, forkedNetwork) { - if (err) return done(err); - - mainWeb3.eth.net.getId(function(err, mainNetwork) { - if (err) return done(err); - - assert.equal(mainNetwork, forkedNetwork); - done(); - }); - }) - }); - - after("Shutdown server", function(done) { - forkedWeb3._provider.connection.close() - forkedServer.close(function(serverCloseErr) { - forkedWeb3.setProvider(); - let mainProvider = mainWeb3._provider; - mainWeb3.setProvider(); - mainProvider.close(function(providerCloseErr) { - if (serverCloseErr) return done(serverCloseErr); - if (providerCloseErr) return done(providerCloseErr); - done() - }); - }); - }); -}); diff --git a/test/forking_deploy_after_fork.js b/test/forking_deploy_after_fork.js deleted file mode 100644 index e25bbc224a..0000000000 --- a/test/forking_deploy_after_fork.js +++ /dev/null @@ -1,135 +0,0 @@ -var Web3 = require('web3'); -var Web3WsProvider = require('web3-providers-ws'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var fs = require("fs"); -var solc = require("solc"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -var logger = { - log: function(msg) { /*console.log(msg)*/ } -}; - -/** - * NOTE: Naming in these tests is a bit confusing. Here, the "main chain" - * is the main chain the tests interact with; and the "forked chain" is the - * chain that _was forked_. This is in contrast to general naming, where the - * main chain represents the main chain to be forked (like the Ethereum live - * network) and the fork chaing being "the fork". - */ - -describe("Contract Deployed on Main Chain After Fork", function() { - var contract; - var contractAddress; - var forkedServer; - var mainAccounts; - - var forkedWeb3 = new Web3(); - var mainWeb3 = new Web3(); - - var forkedTargetUrl = "ws://localhost:21345"; - - before("set up test data", function() { - this.timeout(10000) - var source = fs.readFileSync("./test/Example.sol", {encoding: "utf8"}); - var result = solc.compile(source, 1); - - // Note: Certain properties of the following contract data are hardcoded to - // maintain repeatable tests. If you significantly change the solidity code, - // make sure to update the resulting contract data with the correct values. - contract = { - solidity: source, - abi: result.contracts[":Example"].interface, - binary: "0x" + result.contracts[":Example"].bytecode, - position_of_value: "0x0000000000000000000000000000000000000000000000000000000000000000", - expected_default_value: 5, - call_data: { - gas: '0x2fefd8', - gasPrice: '0x01', // This is important, as passing it has exposed errors in the past. - to: null, // set by test - data: '0x3fa4f245' - }, - transaction_data: { - from: null, // set by test - gas: '0x2fefd8', - to: null, // set by test - data: '0x552410770000000000000000000000000000000000000000000000000000000000000019' // sets value to 25 (base 10) - } - }; - }); - - before("Initialize Fallback Ganache server", function(done) { - this.timeout(10000) - forkedServer = Ganache.server({ - // Do not change seed. Determinism matters for these tests. - seed: "let's make this deterministic", - ws: true, - logger: logger - }); - - forkedServer.listen(21345, function(err) { - if (err) return done(err); - done(); - }); - }); - - before("set forkedWeb3 provider", function() { - forkedWeb3.setProvider(new Web3WsProvider(forkedTargetUrl)); - }); - - before("Set main web3 provider, forking from forked chain at this point", function() { - mainWeb3.setProvider(Ganache.provider({ - fork: forkedTargetUrl.replace('ws', 'http'), - logger, - verbose: true, - - // Do not change seed. Determinism matters for these tests. - seed: "a different seed" - })); - }); - - before("Gather main accounts", async function() { - this.timeout(5000) - mainAccounts = await mainWeb3.eth.getAccounts(); - }); - - before("Deploy initial contract", async function() { - const receipt = await mainWeb3.eth.sendTransaction({ - from: mainAccounts[0], - data: contract.binary, - gas: 3141592, - value: mainWeb3.utils.toWei('1', 'ether') - }); - - contractAddress = receipt.contractAddress; - - // Ensure there's *something* there. - const code = await mainWeb3.eth.getCode(contractAddress); - assert.notEqual(code, null); - assert.notEqual(code, "0x"); - assert.notEqual(code, "0x0"); - }); - - it("should send 1 ether to the created contract, checked on the forked chain", async function() { - const balance = await mainWeb3.eth.getBalance(contractAddress); - - assert.equal(balance, mainWeb3.utils.toWei('1', 'ether')); - }) - - after("Shutdown server", function(done) { - forkedWeb3._provider.connection.close() - forkedServer.close(function(serverCloseErr) { - forkedWeb3.setProvider(); - let mainProvider = mainWeb3._provider; - mainWeb3.setProvider(); - mainProvider.close(function(providerCloseErr) { - if (serverCloseErr) return done(serverCloseErr); - if (providerCloseErr) return done(providerCloseErr); - done() - }); - }); - }); -}); diff --git a/test/forkingasprovider.js b/test/forkingasprovider.js deleted file mode 100644 index e5ff07537e..0000000000 --- a/test/forkingasprovider.js +++ /dev/null @@ -1,133 +0,0 @@ -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var solc = require("solc"); -var to = require("../lib/utils/to.js"); -var async = require("async"); -var Web3 = require('web3'); -var fs = require("fs"); -var assert = require("assert"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -var logger = { - log: function(msg) { /*noop*/ } -}; - -/** - * NOTE: Naming in these tests is a bit confusing. Here, the "main chain" - * is the main chain the tests interact with; and the "forked chain" is the - * chain that _was forked_. This is in contrast to general naming, where the - * main chain represents the main chain to be forked (like the Ethereum live - * network) and the fork chaing being "the fork". - */ - -describe("Forking using a Provider", function() { - var contract; - var forkedProvider = Ganache.provider({ - logger: logger, - seed: "main provider" - }); - var mainProvider; - var forkedWeb3 = new Web3(forkedProvider); - var mainWeb3; - var forkedAccounts; - var contractAddress; - - var forkBlockNumber; - var initialDeployTransactionHash; - - before("set up test data", function() { - this.timeout(5000) - var source = fs.readFileSync("./test/Example.sol", {encoding: "utf8"}); - var result = solc.compile(source, 1); - - // Note: Certain properties of the following contract data are hardcoded to - // maintain repeatable tests. If you significantly change the solidity code, - // make sure to update the resulting contract data with the correct values. - contract = { - solidity: source, - abi: result.contracts[":Example"].interface, - binary: "0x" + result.contracts[":Example"].bytecode, - position_of_value: "0x0000000000000000000000000000000000000000000000000000000000000000", - expected_default_value: 5, - call_data: { - gas: '0x2fefd8', - gasPrice: '0x01', // This is important, as passing it has exposed errors in the past. - to: null, // set by test - data: '0x3fa4f245' - }, - transaction_data: { - from: null, // set by test - gas: '0x2fefd8', - to: null, // set by test - data: '0x552410770000000000000000000000000000000000000000000000000000000000000019' // sets value to 25 (base 10) - } - }; - }); - - before("Gather forked accounts", function(done) { - forkedWeb3.eth.getAccounts(function(err, f) { - if (err) return done(err); - forkedAccounts = f; - done(); - }); - }); - - before("Deploy initial contracts", function(done) { - forkedWeb3.eth.sendTransaction({ - from: forkedAccounts[0], - data: contract.binary, - gas: 3141592 - }, function(err, tx) { - if (err) { return done(err); } - - // Save this for a later test. - initialDeployTransactionHash = tx; - - forkedWeb3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - - contractAddress = receipt.contractAddress; - - forkedWeb3.eth.getCode(contractAddress, function(err, code) { - if (err) return done(err); - - // Ensure there's *something* there. - assert.notEqual(code, null); - assert.notEqual(code, "0x"); - assert.notEqual(code, "0x0"); - - done(); - }); - }); - }); - }); - - before("Set up main provider and web3 instance", function() { - mainProvider = Ganache.provider({ - fork: forkedProvider, - logger: logger, - seed: "forked provider" - }); - mainWeb3 = new Web3(mainProvider); - }); - - // NOTE: This is the only real test in this file. Since we have another forking test file filled - // with good tests, this one simply ensures the forked feature still works by testing that we can - // grab data from the forked chain when a provider instance is passed (instead of a URL). If this - // one passes, it should follow that the rest of the forking features should work as normal. - it("gets code correctly via the main chain (i.e., internally requests it from forked chain)", function(done) { - mainWeb3.eth.getCode(contractAddress, function(err, code) { - if (err) return done(err); - - // Ensure there's *something* there. - assert.notEqual(code, null); - assert.notEqual(code, "0x"); - assert.notEqual(code, "0x0"); - - done(); - }); - }); - -}); diff --git a/test/gas.js b/test/gas.js deleted file mode 100644 index 1b577c6044..0000000000 --- a/test/gas.js +++ /dev/null @@ -1,423 +0,0 @@ -const Web3 = require('web3'); -const assert = require('assert'); -const Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -const fs = require("fs"); -const path = require("path"); -const solc = require("solc"); -const to = require("../lib/utils/to.js"); -const pify = require("pify"); -const RSCLEAR_REFUND = 15000; -const RSELFDESTRUCT_REFUND = 24000; - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -let mnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat' - -describe("Gas", function() { - let estimateGasContractData; - let estimateGasContractAbi; - let EstimateGasContract; - let estimateGasInstance; - let deploymentReceipt; - - const provider = new Ganache.provider({mnemonic}); - const web3 = new Web3(provider); - let accounts = []; - - before("get accounts", async function() { - accounts = await web3.eth.getAccounts(); - }); - - before("compile source", async function() { - this.timeout(10000); - const source = fs.readFileSync(path.join(__dirname, "EstimateGas.sol"), "utf8"); - const result = solc.compile({sources: {"EstimateGas.sol": source}}, 1); - - estimateGasContractData = "0x" + result.contracts["EstimateGas.sol:EstimateGas"].bytecode; - estimateGasContractAbi = JSON.parse(result.contracts["EstimateGas.sol:EstimateGas"].interface); - - EstimateGasContract = new web3.eth.Contract(estimateGasContractAbi); - let promiEvent = EstimateGasContract.deploy({data: estimateGasContractData}) - .send({from: accounts[0], gas: 3141592}); - - promiEvent.on('receipt', function (receipt) { - deploymentReceipt = receipt; - }) - - estimateGasInstance = await promiEvent; - }); - - after("cleanup", function() { - web3.setProvider(null); - provider.close(() => {}); - }); - - async function deployContract(tempWeb3){ - let contract = new tempWeb3.eth.Contract(estimateGasContractAbi); - - return await (contract.deploy({ data: estimateGasContractData }) - .send({ from: accounts[0], gas: 3141592 })); - } - - describe("Refunds", function() { - it("accounts for Rsclear Refund in gasEstimate", async () => { - const from = accounts[0]; - const options = {from, gas: 5000000}; - - await estimateGasInstance.methods.reset().send(options); // prime storage by making sure it is set to 0 - - const method = estimateGasInstance.methods.triggerRsclearRefund(); - - let gasEstimate = await method.estimateGas(options); - - let receipt = await method.send({from, gas: gasEstimate}); - - assert.strictEqual(receipt.gasUsed, gasEstimate - RSCLEAR_REFUND); - assert.strictEqual(receipt.gasUsed, receipt.cumulativeGasUsed); - }); - - - it("accounts for Rselfdestruct Refund in gasEstimate", async () => { - const from = accounts[0]; - const options = {from, gas: 5000000}; - - const instance = await deployContract(web3); - await instance.methods.reset().send(options); // prime storage by making sure it is set to 0 - - const method = instance.methods.triggerRselfdestructRefund(); - - let gasEstimate = await method.estimateGas(options); - - let receipt = await method.send({from, gas: gasEstimate}); - - assert.strictEqual(receipt.gasUsed, gasEstimate - RSELFDESTRUCT_REFUND); - assert.strictEqual(receipt.gasUsed, receipt.cumulativeGasUsed); - }); - - it("accounts for Rsclear and Rselfdestruct Refunds in gasEstimate", async () => { - const from = accounts[0]; - - const instance = await deployContract(web3); - await instance.methods.reset().send({from, gas: 5000000}); // prime storage by making sure it is set to 0 - - const method = instance.methods.triggerAllRefunds(); - - const gasEstimate = await method.estimateGas({from}); - - let receipt = await method.send({from, gas: gasEstimate}); - - assert.strictEqual(receipt.gasUsed, gasEstimate - RSELFDESTRUCT_REFUND - RSCLEAR_REFUND); - assert.strictEqual(receipt.gasUsed, receipt.cumulativeGasUsed); - }) - - - it("accounts for Rsclear and Rselfdestruct Refunds in gasEstimate with multiple transaction in the block", async () => { - const ganacheProvider = Ganache.provider({ - blockTime: .5, // seconds - mnemonic: mnemonic - }) - - let tempWeb3; - - try { - tempWeb3 = new Web3(ganacheProvider); - - const from = (await tempWeb3.eth.getAccounts())[0]; - - let transactions = [{ - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[2], - "to": accounts[1], - "nonce": "0x0" - }, { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[2], - "to": accounts[1], - "nonce": "0x1" - }, { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[1],// < - "to": accounts[2], // <^ reversed tx order - "nonce": "0x0" - }] - - // Precondition - const initialBlockNumber = await tempWeb3.eth.getBlockNumber(); - assert.deepStrictEqual(initialBlockNumber, 0, 'Current Block Should be 0'); - - - const localGasInstance = await deployContract(tempWeb3); - - await localGasInstance.methods.reset().send({from, gas: 5000000}); // prime storage by making sure it is set to 0 - const method = localGasInstance.methods.triggerAllRefunds(); - const gasEstimate = await method.estimateGas({from}); - - let hashes = await Promise.all(transactions.map((transaction) => { - let promiEvent = tempWeb3.eth.sendTransaction(transaction); - - return new Promise((accept) => { - promiEvent.once('transactionHash', async (hash) => { - - // Ensure there's no receipt since the transaction hasn't yet been processed. Ensure IntervalMining - let receipt = await tempWeb3.eth.getTransactionReceipt(hash); - assert.equal(receipt, null, "No receipt since the transaction hasn't yet been processed."); - - accept(hash); - }) - }); - })); - let currentBlockNumber = await tempWeb3.eth.getBlockNumber(); - assert.deepStrictEqual(currentBlockNumber, 2, 'Current Block Should be 2'); - - const receipt = await method.send({from, gas: gasEstimate}); - - let transactionCostMinusRefund = gasEstimate - RSELFDESTRUCT_REFUND - RSCLEAR_REFUND; - assert.strictEqual(receipt.gasUsed, transactionCostMinusRefund); - - - let receipts = await Promise.all(hashes.map((hash) => tempWeb3.eth.getTransactionReceipt(hash))); - assert.deepStrictEqual(receipts[0].gasUsed, receipts[1].gasUsed, 'Tx1 and Tx2 should cost the same gas.'); - assert.deepStrictEqual(receipts[1].gasUsed, receipts[2].gasUsed, 'Tx2 and Tx3 should cost the same gas. -> Tx1 gas === Tx3 gas Transitive'); - assert.deepStrictEqual(receipts[1].transactionIndex > receipts[2].transactionIndex, true, '(Tx3 has a lower nonce) -> (Tx3 index is < Tx2 index)'); - let currentBlock = await tempWeb3.eth.getBlock(receipts[0].blockNumber); - - // ( Tx3 has a lower nonce -> Tx3 index is < Tx2 index ) -> cumulative gas Tx2 > Tx3 > Tx1 - let isAccumulating = (receipts[1].cumulativeGasUsed > receipts[2].cumulativeGasUsed) && (receipts[2].cumulativeGasUsed > receipts[0].cumulativeGasUsed); - assert.deepStrictEqual(isAccumulating, true, 'Cumulative gas should be accumulating for any transactions in the same block.'); - assert.deepStrictEqual(receipts[0].gasUsed, receipts[0].cumulativeGasUsed, 'Gas and cumulative gas should be equal for the FIRST Tx.'); - assert.notDeepStrictEqual(receipts[1].gasUsed, receipts[1].cumulativeGasUsed, 'Gas and cumulative gas should NOT be equal for the Second Tx.'); - assert.notDeepStrictEqual(receipts[2].gasUsed, receipts[2].cumulativeGasUsed, 'Gas and cumulative gas should NOT be equal for the Third Tx.'); - - let totalGas = receipts[0].gasUsed + receipts[1].gasUsed + receipts[2].gasUsed; - assert.deepStrictEqual(totalGas + transactionCostMinusRefund, receipts[1].cumulativeGasUsed, "Total Gas should equal the final tx.cumulativeGas") - assert.deepStrictEqual(totalGas + transactionCostMinusRefund, currentBlock.gasUsed, "Total Gas should be equal to the currentBlock.gasUsed") - - } catch (e){ - assert(false, e); - } finally { - // clean up after ourselves - if (tempWeb3) { - tempWeb3.setProvider(null); - } - await pify(ganacheProvider.close)(); - } - }); - - it("clears mapping storage slots", async () =>{ - const options = {from: accounts[0]}; - - await estimateGasInstance.methods.reset().send({from: options.from, gas: 5000000}); - - const uintsa = await estimateGasInstance.methods.uints(1).call(); - assert.equal(uintsa, "0", "initial value is not correct"); - - const receipta = await estimateGasInstance.methods.store(1).send(options); - assert.equal(receipta.status, true, "storing value did not work"); - - const uintsb = await estimateGasInstance.methods.uints(1).call(); - assert.equal(uintsb, "1", "set value is incorrect"); - - const receiptb = await estimateGasInstance.methods.clear().send(options); - assert.equal(receiptb.status, true, "clearing value did not work"); - - const uintsc = await estimateGasInstance.methods.uints(1).call(); - assert.equal(uintsc, "0", "cleared value is not correct"); - }); - }); - - describe("Estimation", function() { - - async function testTransactionEstimate(contractFn, args, options) { - await estimateGasInstance.methods.reset().send({from: options.from, gas: 5000000}); - const method = contractFn(...args); - const gasEstimate = await method.estimateGas(options); - const receipt = await method.send(options); - - assert.equal(receipt.status, 1, 'Transaction must succeed'); - assert.equal(receipt.gasUsed, gasEstimate, "gasUsed"); - assert.equal(receipt.cumulativeGasUsed, gasEstimate, "estimate"); - } - - it("matches estimate for deployment", async function() { - let gasEstimate = await EstimateGasContract.deploy({ data: estimateGasContractData }) - .estimateGas({ from: accounts[1]}) - - assert.deepStrictEqual(deploymentReceipt.gasUsed, gasEstimate); - assert.deepStrictEqual(deploymentReceipt.cumulativeGasUsed, gasEstimate); - }); - - it("matches usage for complex function call (add)", async function() { - this.timeout(10000) - await testTransactionEstimate(estimateGasInstance.methods.add, [toBytes("Tim"), toBytes("A great guy"), 10], {from: accounts[0], gas: 3141592}); - }); - - it("matches usage for complex function call (transfer)", async function() { - this.timeout(10000) - await testTransactionEstimate(estimateGasInstance.methods.transfer, ["0x0123456789012345678901234567890123456789", 5, toBytes("Tim")], {from: accounts[0], gas: 3141592}); - }); - - function toBytes(s) { - let bytes = Array.prototype.map.call(s, function(c) { - return c.codePointAt(0) - }) - - return to.hex(Buffer.from(bytes)) - } - - }); - - describe('Expenditure', function() { - async function testGasExpenseIsCorrect(expectedGasPrice, setGasPriceOnTransaction = false, w3 = web3) { - const transferAmount = w3.utils.toBN(w3.utils.toWei('5', 'finney')); - - expectedGasPrice = w3.utils.toBN(expectedGasPrice); - - const initialBalance = await w3.utils.toBN(await w3.eth.getBalance(accounts[0])); - - let params = { - from: accounts[0], - to: accounts[1], - value: transferAmount - } - - if (setGasPriceOnTransaction) { - params.gasPrice = expectedGasPrice - } - - const receipt = await w3.eth.sendTransaction(params); - const gasUsed = w3.utils.toBN(receipt.gasUsed); - - const finalBalance = w3.utils.toBN(await w3.eth.getBalance(accounts[0])); - const deltaBalance = initialBalance.sub(finalBalance) - - // the amount we paid in excess of our transferAmount is what we spent on gas - const gasExpense = deltaBalance.sub(transferAmount) - - assert(!gasExpense.eq(w3.utils.toBN('0')), 'Calculated gas expense must be nonzero.') - - // gas expense is just gasPrice * gasUsed, so just solve accordingly - const actualGasPrice = gasExpense.div(gasUsed) - - assert(expectedGasPrice.eq(actualGasPrice), - `Gas price used by EVM (${to.hex(actualGasPrice)}) was different from expected gas price (${to.hex(expectedGasPrice)})`) - } - - it('should calculate gas expenses correctly in consideration of the default gasPrice', async function() { - await testGasExpenseIsCorrect(await web3.eth.getGasPrice()) - }) - - it('should calculate gas expenses correctly in consideration of the requested gasPrice', async function() { - await testGasExpenseIsCorrect('0x10000', true) - }) - - it('should calculate gas expenses correctly in consideration of a user-defined default gasPrice', async function() { - let gasPrice = '0x2000' - let provider = new Ganache.provider({ mnemonic, gasPrice }); - let tempWeb3; - try { - tempWeb3 = new Web3(provider); - await testGasExpenseIsCorrect(gasPrice, false, new Web3(Ganache.provider({ mnemonic, gasPrice }))) - } catch (e) { - if (tempWeb3) { - tempWeb3.setProvider(null); - } - provider.stop(() => {}) - } - }) - - it('should calculate cumalativeGas and gasUsed correctly when multiple transactions are in a block', async function (){ - let provider = Ganache.provider({ - blockTime: .5, // seconds - mnemonic: mnemonic - }); - - let tempWeb3; - - try { - tempWeb3 = new Web3(provider); - - let transactions = [{ - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x0" - }, { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x1" - }, { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[1],// < - "to": accounts[0], // <^ reversed tx order - "nonce": "0x0" - }] - - // Precondition - const initialBlockNumber = await tempWeb3.eth.getBlockNumber(); - assert.deepStrictEqual(initialBlockNumber, 0, 'Current Block Should be 0'); - - let hashes = await Promise.all(transactions.map((transaction) => { - let promiEvent = tempWeb3.eth.sendTransaction(transaction); - - return new Promise((accept) => { - promiEvent.once('transactionHash', async (hash) => { - - // Ensure there's no receipt since the transaction hasn't yet been processed. Ensure IntervalMining - let receipt = await tempWeb3.eth.getTransactionReceipt(hash); - assert.equal(receipt, null, "No receipt since the transaction hasn't yet been processed."); - - accept(hash); - }) - }); - })); - - // Wait .75 seconds (1.5x the mining interval) then get the receipt. It should be processed. - await delay(750) - - let currentBlockNumber = await tempWeb3.eth.getBlockNumber(); - assert.deepStrictEqual(currentBlockNumber, 1, 'Current Block Should be 1'); - - let currentBlock = await tempWeb3.eth.getBlock(currentBlockNumber); - - let receipts = await Promise.all(hashes.map((hash) => tempWeb3.eth.getTransactionReceipt(hash))) - - assert.deepStrictEqual(receipts[0].gasUsed, receipts[1].gasUsed, 'Tx1 and Tx2 should cost the same gas.'); - assert.deepStrictEqual(receipts[1].gasUsed, receipts[2].gasUsed, 'Tx2 and Tx3 should cost the same gas. -> Tx1 gas === Tx3 gas Transitive'); - assert.deepStrictEqual(receipts[1].transactionIndex > receipts[2].transactionIndex, true, '(Tx3 has a lower nonce) -> (Tx3 index is < Tx2 index)'); - - // ( Tx3 has a lower nonce -> Tx3 index is < Tx2 index ) -> cumulative gas Tx2 > Tx3 > Tx1 - let isAccumulating = (receipts[1].cumulativeGasUsed > receipts[2].cumulativeGasUsed) && (receipts[2].cumulativeGasUsed > receipts[0].cumulativeGasUsed); - assert.deepStrictEqual(isAccumulating, true, 'Cumulative gas should be accumulating for any transactions in the same block.'); - assert.deepStrictEqual(receipts[0].gasUsed, receipts[0].cumulativeGasUsed, 'Gas and cumulative gas should be equal for the FIRST Tx.'); - assert.notDeepStrictEqual(receipts[1].gasUsed, receipts[1].cumulativeGasUsed, 'Gas and cumulative gas should NOT be equal for the Second Tx.'); - assert.notDeepStrictEqual(receipts[2].gasUsed, receipts[2].cumulativeGasUsed, 'Gas and cumulative gas should NOT be equal for the Third Tx.'); - - let totalGas = receipts[0].gasUsed + receipts[1].gasUsed + receipts[2].gasUsed; - assert.deepStrictEqual(totalGas, receipts[1].cumulativeGasUsed, "Total Gas should be equal the final tx.cumulativeGas") - assert.deepStrictEqual(totalGas, currentBlock.gasUsed, "Total Gas should be equal to the currentBlock.gasUsed") - } catch (e){ - assert(false, e) - } finally { - if (tempWeb3) { - tempWeb3.setProvider(null); - } - await pify(provider.close)(); - } - }); - }); -}); - -async function delay(duration) { - await new Promise((accept) => { - setTimeout(accept, duration) - }); -} diff --git a/test/helpers/contracts.js b/test/helpers/contracts.js deleted file mode 100644 index 1fd1bf87a1..0000000000 --- a/test/helpers/contracts.js +++ /dev/null @@ -1,41 +0,0 @@ -const fs = require('fs') -const solc = require('solc') -const path = require('path') - -async function compileAndDeploy(contractPath, contractName, web3) { - let contractFilename = path.basename(contractPath) - - let source = fs.readFileSync(contractPath, "utf8"); - - let result = solc.compile({sources: {[contractFilename]: source}}, 1); - - let bytecode = "0x" + result.contracts[`${contractFilename}:${contractName}`].bytecode; - let abi = JSON.parse(result.contracts[`${contractFilename}:${contractName}`].interface); - - let contract = new web3.eth.Contract(abi); - - let accounts = await web3.eth.getAccounts() - let block = await web3.eth.getBlock("latest"); - let gasLimit = block.gasLimit; - - - let instance = await contract.deploy({data: bytecode}).send({from: accounts[0], gas: gasLimit}) - - // TODO: ugly workaround - not sure why this is necessary. - if (!instance._requestManager.provider) { - instance._requestManager.setProvider(web3.eth._provider); - } - - return { - source, - bytecode, - abi, - contract, - instance - } -} - -exports = module.exports = { - compileAndDeploy -} - diff --git a/test/hex.js b/test/hex.js deleted file mode 100644 index 2f27b88bdd..0000000000 --- a/test/hex.js +++ /dev/null @@ -1,136 +0,0 @@ -var assert = require("assert"); -var Web3 = require("web3"); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var to = require("../lib/utils/to.js"); - -describe("to.rpcQuantityHexString", function() { - it("should print '0x0' for input 0", function(done) { - assert.equal(to.rpcQuantityHexString(0), "0x0"); - done(); - }); - - it("should print '0x0' for input '0'", function(done) { - assert.equal(to.rpcQuantityHexString("0"), "0x0"); - done(); - }); - - it("should print '0x0' for input '000'", function(done) { - assert.equal(to.rpcQuantityHexString("000"), "0x0"); - done(); - }); - - it("should print '0x0' for input '0x000'", function(done) { - assert.equal(to.rpcQuantityHexString("0x000"), "0x0"); - done(); - }); - - it("should print '0x20' for input '0x0020'", function(done) { - assert.equal(to.rpcQuantityHexString("0x0020"), "0x20"); - done(); - }); -}); - -describe("to.rpcDataHexString", function() { - it("should differentiate between a list of 0 items and a list of one 0", function(done) { - assert.notEqual(to.rpcDataHexString(Buffer.from("", "hex")), to.rpcDataHexString(Buffer.from("00", "hex"))); - done(); - }) -}) - -function noLeadingZeros(method, result, path) { - if (!path) { - path = 'result' - } - - if (typeof result === "string") { - if (/^0x/.test(result)) { - assert.equal(result, to.rpcQuantityHexString(result), `Field ${path} in ${method} response has leading zeroes.`); - } - } else if (typeof result === "object") { - for (var key in result) { - if (result.hasOwnProperty(key)) { - if (Array.isArray(result)) { - path += [key] - } else { - path += '.' + key - } - noLeadingZeros(method, result[key], path + (path ? '.' : '') + key); - } - } - } -} - -describe("JSON-RPC Response", function() { - var web3 = new Web3(); - var provider = Ganache.provider(); - web3.setProvider(provider); - - var accounts; - before(function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - // skipping this test for now as they aren't verifying the right thing that - // is, leading zeroes are fine in some response fields. we need a better model - // of expected response formatting/padding. - it.skip("should not have leading zeros in rpc quantity hex strings", function(done) { - var request = { - "jsonrpc": "2.0", - "method": "eth_getTransactionCount", - "params": [ - accounts[0], - "pending" - ], - "id": 1 - }; - - provider.sendAsync(request, function(err, result) { - noLeadingZeros('eth_getTransactionCount', result); - - request = { - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [ - { - "from": accounts[0], - "to": accounts[1], - "value": "0x100000000" - } - ], - "id": 2 - }; - - provider.sendAsync(request, function() { - // Ignore eth_sendTransaction result, it returns the transaction hash. - // A transaction hash is a 'DATA' type, which can have leading zeroes - // to pad it to an even string length (4 bit per char, so whole bytes). - - request = { - "jsonrpc": "2.0", - "method": "eth_getTransactionCount", - "params": [ - accounts[0], - "pending" - ], - "id": 3 - }; - - provider.sendAsync(request, function(err, result) { - noLeadingZeros('eth_getTransactionCount', result); - done(); - }); - }); - }); - }); -}); - -describe("to.hex", function() { - it("should print '0x' for input '' (blank)", function(done) { - assert.equal(to.hex(Buffer("")), "0x"); - done(); - }); -}) \ No newline at end of file diff --git a/test/interval_mining.js b/test/interval_mining.js deleted file mode 100644 index 4c7da5092e..0000000000 --- a/test/interval_mining.js +++ /dev/null @@ -1,176 +0,0 @@ -var BN = require('bn.js'); -var Web3 = require('web3'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require('assert'); -var to = require("../lib/utils/to.js"); -var solc = require("solc"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -describe("Interval Mining", function() { - var web3; - - var mnemonic = "into trim cross then helmet popular suit hammer cart shrug oval student"; - var first_address = "0x604a95C9165Bc95aE016a5299dd7d400dDDBEa9A"; - - it("should mine a block on the interval", function(done) { - this.timeout(5000); - - web3 = new Web3(Ganache.provider({ - blockTime: 0.5, // seconds - mnemonic: mnemonic - })); - - // Get the first block (pre-condition) - web3.eth.getBlockNumber(function(err, number) { - if (err) return done(err); - assert.equal(number, 0); - - // Wait 1.25 seconds (two and a half mining intervals) then get the next block. - // It should be block number 2 (the third block). We wait more than one iteration - // to ensure the timeout gets reset. - - setTimeout(function() { - // Get the first block (pre-condition) - web3.eth.getBlockNumber(function(err, latest_number) { - assert.equal(latest_number, 2); - done(); - }); - }, 1250); - }); - }); - - it("shouldn't instamine when mining on an interval", function(done) { - this.timeout(5000); - - web3 = new Web3(Ganache.provider({ - blockTime: 0.25, // seconds - mnemonic: mnemonic - })); - - // Get the first block (pre-condition) - web3.eth.getBlockNumber(function(err, number) { - if (err) return done(err); - assert.equal(number, 0); - - // Queue a transaction - web3.eth.sendTransaction({ - from: first_address, - to: "0x1234567890123456789012345678901234567890", - value: web3.utils.toWei(new BN(1), "ether"), - gas: 90000 - }, function(err, tx) { - if (err) return done(err); - - // Ensure there's no receipt since the transaction hasn't yet been processed. - web3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - - assert.equal(receipt, null); - - // Wait .75 seconds (one and a half mining intervals) then get the receipt. It should be processed. - - setTimeout(function() { - // Get the first block (pre-condition) - web3.eth.getTransactionReceipt(tx, function(err, new_receipt) { - assert.notEqual(new_receipt, null); - done(); - }); - }, 750); - }); - - }); - }); - }); - - it("miner_stop should stop interval mining, and miner_start should start it again", function(done) { - this.timeout(5000); - - web3 = new Web3(Ganache.provider({ - blockTime: 0.5, // seconds - mnemonic: mnemonic - })); - - // Stop mining - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "miner_stop", - id: new Date().getTime() - }, function(err, result) { - if (err) return done(err); - if (result.error) return done(result.error.message); - - // Get the first block (pre-condition) - web3.eth.getBlockNumber(function(err, initial_number) { - if (err) return done(err); - - // Wait .75 seconds (one and a half mining intervals) and ensure - // the block number hasn't increased. - setTimeout(function() { - web3.eth.getBlockNumber(function(err, stopped_number) { - if (err) return done(err); - assert.equal(stopped_number, initial_number); - - // Start mining again - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "miner_start", - params: [1], - id: new Date().getTime() - }, function(err, result) { - if (err) return done(err); - if (result.error) return done(result.error.message); - - // Wait .75 seconds (one and a half mining intervals) and ensure - // the block number has increased by one. - setTimeout(function() { - web3.eth.getBlockNumber(function(err, last_number) { - if (err) return done(err); - - assert(last_number > stopped_number); - done(); - }); - }, 750) - - }); - }); - }, 750) - - }); - }); - }); - - it("should log runtime errors to the log", async function() { - this.timeout(5000); - - var logData = ""; - var logger = { - log: function(message) { - logData += message + "\n"; - } - }; - - web3 = new Web3(Ganache.provider({ - blockTime: 0.5, // seconds - mnemonic: mnemonic, - logger: logger - })); - - var result = solc.compile({sources: {"Example.sol": "pragma solidity ^0.4.2; contract Example { function Example() {throw;} }"}}, 1); - var bytecode = "0x" + result.contracts["Example.sol:Example"].bytecode; - - try { - let receipt = await web3.eth.sendTransaction({ - from: first_address, - data: bytecode, - gas: 3141592 - }); - assert.fail("Contract deploy promise should have rejected"); - } catch (e) { - assert(logData.indexOf("Runtime Error: revert") >= 0); - } - }); - -}); diff --git a/test/mining.js b/test/mining.js deleted file mode 100644 index 2fd85ead6f..0000000000 --- a/test/mining.js +++ /dev/null @@ -1,337 +0,0 @@ -var BN = require('bn.js'); -var Web3 = require('web3'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require('assert'); -var to = require("../lib/utils/to.js"); -var solc = require("solc"); -var pify = require("pify"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -describe("Mining", function() { - var web3 = new Web3(Ganache.provider({ - vmErrorsOnRPCResponse: true - //logger: console, - })); - var accounts; - var snapshot_id; - var badBytecode; - var goodBytecode; - - before("compile solidity code that causes runtime errors", async function() { - this.timeout(10000) - let result = await compileSolidity("pragma solidity ^0.4.2; contract Example { function Example() {throw;} }"); - badBytecode = result.code; - }); - - before("compile solidity code that causes an event", async function() { - this.timeout(10000) - let result = await compileSolidity("pragma solidity ^0.4.2; contract Example { event Event(); function Example() { Event(); } }"); - goodBytecode = result.code; - }); - - beforeEach("checkpoint, so that we can revert later", async function() { - let res = await pify(web3.currentProvider.send)({ - jsonrpc: "2.0", - method: "evm_snapshot", - id: new Date().getTime() - }); - - snapshot_id = res.result; - }); - - afterEach("revert back to checkpoint", async function() { - await pify(web3.currentProvider.send)({ - jsonrpc: "2.0", - method: "evm_revert", - params: [snapshot_id], - id: new Date().getTime() - }); - }); - - // Everything's a Promise to add in readibility. - async function getBlockNumber() { - return to.number(await web3.eth.getBlockNumber()) - }; - - async function startMining() { - await pify(web3.currentProvider.send)({ - jsonrpc: "2.0", - method: "miner_start", - params: [1], - id: new Date().getTime() - }); - } - - async function stopMining() { - await pify(web3.currentProvider.send)({ - jsonrpc: "2.0", - method: "miner_stop", - id: new Date().getTime() - }); - } - - async function checkMining() { - let response = await pify(web3.currentProvider.send)({ - jsonrpc: "2.0", - method: "eth_mining", - id: new Date().getTime() - }); - - return response.result; - } - - async function mineSingleBlock() { - let result = await pify(web3.currentProvider.send)({ - jsonrpc: "2.0", - method: "evm_mine", - id: new Date().getTime() - }); - assert.deepEqual(result.result, "0x0"); - } - - async function queueTransaction(from, to, gasLimit, value, data) { - let response = await pify(web3.currentProvider.send)({ - jsonrpc: "2.0", - method: "eth_sendTransaction", - id: new Date().getTime(), - params: [{ - from: from, - to: to, - gas: gasLimit, - value: value, - data: data - }] - }) - if (response.error) { - throw new Error(response.error.message) - } - return response.result - } - - async function getCode(address) { - return await web3.eth.getCode(address); - }; - - function compileSolidity(source) { - let result = solc.compile({sources: {"Contract.sol": source}}); - return Promise.resolve({code: "0x" + result.contracts[Object.keys(result.contracts)[0]].bytecode}) - }; - - before(async function() { - accounts = await web3.eth.getAccounts() - }); - - it("should mine a single block with two queued transactions", async function() { - await stopMining() - let blockNumber = await getBlockNumber(); - - let tx1 = await queueTransaction(accounts[0], accounts[1], 90000, web3.utils.toWei(new BN(2), "ether")); - let receipt1 = await web3.eth.getTransactionReceipt(tx1); - assert.equal(receipt1, null); - - let tx2 = await queueTransaction(accounts[0], accounts[1], 90000, web3.utils.toWei(new BN(3), "ether")); - let receipt2 = await web3.eth.getTransactionReceipt(tx2); - assert.equal(receipt2, null); - - await startMining(); - - let receipts = await Promise.all([web3.eth.getTransactionReceipt(tx1), web3.eth.getTransactionReceipt(tx2)]); - - assert.equal(receipts.length, 2); - - assert.notEqual(receipts[0], null); - assert.equal(receipts[0].transactionHash, tx1); - assert.notEqual(receipts[1], null); - assert.equal(receipts[1].transactionHash, tx2); - assert.equal(receipts[0].blockNumber, receipts[1].blockNumber, "Transactions should be mined in the same block."); - - let number = await getBlockNumber(); - assert.equal(number, blockNumber + 1); - }); - - it("should mine two blocks when two queued transactions won't fit into a single block", async function() { - // This is a very similar test to the above, except the gas limits are much higher - // per transaction. This means the Ganache will react differently and process - // each transaction it its own block. - - await stopMining(); - let blockNumber = await getBlockNumber(); - - let tx1 = await queueTransaction(accounts[0], accounts[1], 4000000, web3.utils.toWei(new BN(2), "ether")); - let receipt1 = await web3.eth.getTransactionReceipt(tx1); - assert.equal(receipt1, null); - - let tx2 = await queueTransaction(accounts[0], accounts[1], 4000000, web3.utils.toWei(new BN(3), "ether")); - let receipt2 = await web3.eth.getTransactionReceipt(tx2); - assert.equal(receipt2, null); - - await startMining(); - - let receipts = await Promise.all([web3.eth.getTransactionReceipt(tx1), web3.eth.getTransactionReceipt(tx2)]); - - assert.equal(receipts.length, 2); - - assert.notEqual(receipts[0], null); - assert.equal(receipts[0].transactionHash, tx1); - - assert.notEqual(receipts[1], null); - assert.equal(receipts[1].transactionHash, tx2); - - assert.notEqual(receipts[0].blockNumber, receipts[1].blockNumber, "Transactions should not be mined in the same block."); - - let number = await getBlockNumber(); - assert.equal(number, blockNumber + 2); - }); - - it("should mine one block when requested, and only one transaction, when two queued transactions together are larger than a single block", async function() { - // This is a very similar test to the above, except we don't start mining again, - // we only mine one block by request. - - await stopMining() - let blockNumber = await getBlockNumber(); - let tx1 = await queueTransaction(accounts[0], accounts[1], 4000000, web3.utils.toWei(new BN(2), "ether")); - let receipt1 = await web3.eth.getTransactionReceipt(tx1); - assert.equal(receipt1, null); - - let tx2 = await queueTransaction(accounts[0], accounts[1], 4000000, web3.utils.toWei(new BN(3), "ether")); - let receipt2 = await web3.eth.getTransactionReceipt(tx2); - assert.equal(receipt2, null); - - await mineSingleBlock(); - - let receipts = await Promise.all([web3.eth.getTransactionReceipt(tx1), web3.eth.getTransactionReceipt(tx2)]); - - assert.equal(receipts.length, 2); - - assert.notEqual(receipts[0], null); - assert.equal(receipts[0].transactionHash, tx1); - - assert.equal(receipts[1], null); - - let number = await getBlockNumber(); - assert.equal(number, blockNumber + 1); - }); - - it("should error if queued transaction exceeds the block gas limit", async function() { - try { - await stopMining() - let tx1 = await queueTransaction(accounts[0], accounts[1], 10000000, web3.utils.toWei(new BN(2), "ether")); - assert.fail("Transaction was processed without erroring; gas limit should have been too high"); - } catch (err) { - // We caught an error like we expected. Ensure it's the right error, or rethrow. - if (err.message.toLowerCase().indexOf("exceeds block gas limit") < 0) { - assert.fail("Did not receive expected error; instead received: " + err); - } - } - }); - - it("should error via instamining when queued transaction throws a runtime errors", async function() { - try { - await startMining() - // This transaction should be processed immediately. - let tx1 = await queueTransaction(accounts[0], null, 3141592, 0, badBytecode); - assert.fail("Execution should never get here as we expected `eth_sendTransaction` to throw an error") - } catch (err) { - if (err.message.indexOf("VM Exception while processing transaction") != 0) { - assert.fail("Received error we didn't expect: " + err); - } - } - }); - - it("should error via evm_mine when queued transaction throws a runtime errors", async function() { - try { - await stopMining() - await queueTransaction(accounts[0], null, 3141592, 0, badBytecode); - await mineSingleBlock(); - assert.fail("Execution should never get here as we expected `evm_mine` to throw an error") - } catch (err) { - if (err.message.indexOf("VM Exception while processing transaction") != 0) { - assert.fail("Received error we didn't expect: " + err); - } - } - }); - - it("should error via evm_mine when multiple queued transactions throw runtime errors in a single block", async function() { - // Note: The two transactions queued in this test do not exceed the block gas limit - // and thus should fit within a single block. - - try { - await stopMining() - await queueTransaction(accounts[0], null, 1000000, 0, badBytecode); - await queueTransaction(accounts[0], null, 1000000, 0, badBytecode); - await mineSingleBlock(); - assert.fail("Execution should never get here as we expected `evm_mine` to throw an error") - } catch (err) { - if (err.message.indexOf("Multiple VM Exceptions while processing transactions") != 0) { - assert.fail("Received error we didn't expect: " + err); - } - // We got the error we wanted. Test passed! - } - }); - - it("should error via miner_start when multiple queued transactions throw runtime errors in multiple blocks", async function() { - // Note: The two transactions queued in this test together DO exceed the block gas limit - // and thus will fit in two blocks, one block each. - - try { - await stopMining() - await queueTransaction(accounts[0], null, 3141592, 0, badBytecode); - await queueTransaction(accounts[0], null, 3141592, 0, badBytecode); - await startMining(); - assert.fail("Execution should never get here as we expected `miner_start` to throw an error") - } catch (err) { - if (err.message.indexOf("Multiple VM Exceptions while processing transactions") != 0) { - assert.fail("Received error we didn't expect: " + err); - } - // We got the error we wanted. Test passed! - } - }); - - it("even if we receive a runtime error, logs for successful transactions need to be processed", async function() { - // Note: The two transactions queued in this test should exist within the same block. - let tx1, tx2; - - try { - await stopMining() - - tx1 = await queueTransaction(accounts[0], null, 1000000, 0, badBytecode); - tx2 = await queueTransaction(accounts[0], null, 1000000, 0, goodBytecode); - - await startMining(); - assert.fail("Execution should never get here as we expected `miner_start` to throw an error") - } catch (err) { - if (err.message.indexOf("VM Exception while processing transaction") != 0) { - assert.fail("Received error we didn't expect: " + err); - } - - // We got the error we wanted. Now check to see if the transaction was processed correctly. - let receiptTx2 = await web3.eth.getTransactionReceipt(tx2) - - // We should have a receipt for the second transaction - it should have been processed. - assert.notEqual(receiptTx2, null); - assert.notEqual(receiptTx2, {}); - - // It also should have logs. - assert.notEqual(receiptTx2.logs.length, 0); - - // Now check that there's code at the address, which means it deployed successfully. - let code = await getCode(receiptTx2.contractAddress); - - // Convert hex to a big number and ensure it's not zero. - assert(web3.utils.toBN(code).eq(0) == false); - - } - }); - - it("should return the correct value for eth_mining when miner started and stopped", async function() { - await stopMining() - let isMining = await checkMining(); - assert(!isMining); - await startMining(); - isMining = await checkMining(); - assert(isMining); - }); -}); diff --git a/test/options/gasLimit.js b/test/options/gasLimit.js deleted file mode 100644 index 66f8775064..0000000000 --- a/test/options/gasLimit.js +++ /dev/null @@ -1,30 +0,0 @@ -const Web3 = require('web3'); -const assert = require('assert'); -const Ganache = require("../../index.js"); -const path = require("path"); - -const mnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat' - -describe('options:gasLimit', function() { - let options = {mnemonic} - let provider = null - let web3 = null - let accounts = [] - - before ('setup web3', async function() { - provider = new Ganache.provider(options) - web3 = new Web3(provider) - }) - - before('get accounts', async function() { - accounts = await web3.eth.getAccounts() - }) - - it('should respect the assigned gasLimit', async function() { - let assignedGasLimit = provider.engine.manager.state.blockchain.blockGasLimit; - let block = await web3.eth.getBlock('latest') - assert.deepEqual(block.gasLimit, assignedGasLimit) - }) -}); - - diff --git a/test/options/gasPrice.js b/test/options/gasPrice.js deleted file mode 100644 index 4a999cfe79..0000000000 --- a/test/options/gasPrice.js +++ /dev/null @@ -1,79 +0,0 @@ -const to = require('../../lib/utils/to'); -const Web3 = require('web3'); -const assert = require('assert'); -const Ganache = require("../../index"); -const path = require("path"); - -const compileAndDeploy = require ('../helpers/contracts').compileAndDeploy - -const mnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat' - -function setUp(options = {mnemonic}, contractName = 'Example') { - let context = { - options: options, - provider: null, - web3: null, - accounts: [], - contractArtifact: {}, - instance: null - } - - before ('setup web3', async function() { - context.provider = new Ganache.provider(context.options) - context.web3 = new Web3(context.provider) - }) - - before('get accounts', async function() { - context.accounts = await context.web3.eth.getAccounts() - }) - - before("compile source", async function() { - this.timeout(10000) - context.contractArtifact = await compileAndDeploy(path.join(__dirname, '..', `${contractName}.sol`), contractName, context.web3) - context.instance = context.contractArtifact.instance - }) - - return context -} - -describe('options:gasPrice', function() { - describe('default gasPrice', function() { - - let context = setUp() - - it('should respect the default gasPrice', async function() { - let assignedGasPrice = context.provider.engine.manager.state.gasPriceVal; - - let receipt = await context.instance.methods.setValue('0x10').send({from: context.accounts[0], gas: 3141592}) - - let transactionHash = receipt.transactionHash; - let tx = await context.web3.eth.getTransaction(transactionHash) - let gasPrice = tx.gasPrice - - assert.deepEqual(to.hex(gasPrice), to.hex(assignedGasPrice)) - }) - - }) - - describe('zero gasPrice', function() { - - let context = setUp({mnemonic, gasPrice: 0}) - - it('should be possible to set a zero gas price', async function() { - let assignedGasPrice = context.provider.engine.manager.state.gasPriceVal; - - assert.deepEqual(assignedGasPrice, '0x0') - - let receipt = await context.instance.methods.setValue('0x10').send({from: context.accounts[0], gas: 3141592}) - - let transactionHash = receipt.transactionHash; - let tx = await context.web3.eth.getTransaction(transactionHash) - let gasPrice = tx.gasPrice - - assert.deepEqual(to.hex(gasPrice), to.hex(assignedGasPrice)) - }) - - }) -}); - - diff --git a/test/persistence.js b/test/persistence.js deleted file mode 100644 index 59f93b164b..0000000000 --- a/test/persistence.js +++ /dev/null @@ -1,167 +0,0 @@ -var Web3 = require('web3'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require('assert'); -var temp = require("temp").track(); -var fs = require("fs"); -var solc = require("solc"); -var memdown = require("memdown"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -var source = fs.readFileSync("./test/Example.sol", {encoding: "utf8"}); -var result = solc.compile(source, 1); -var provider - -// Note: Certain properties of the following contract data are hardcoded to -// maintain repeatable tests. If you significantly change the solidity code, -// make sure to update the resulting contract data with the correct values. -var contract = { - solidity: source, - abi: result.contracts[":Example"].interface, - binary: "0x" + result.contracts[":Example"].bytecode, - position_of_value: "0x0000000000000000000000000000000000000000000000000000000000000000", - expected_default_value: 5, - call_data: { - gas: '0x2fefd8', - gasPrice: '0x01', // This is important, as passing it has exposed errors in the past. - to: null, // set by test - data: '0x3fa4f245' - }, - transaction_data: { - from: null, // set by test - gas: '0x2fefd8', - to: null, // set by test - data: '0x552410770000000000000000000000000000000000000000000000000000000000000019' // sets value to 25 (base 10) - } -}; - -var runTests = function(providerInit) { - describe("Persistence ", function() { - var web3 = new Web3(); - var accounts; - var tx_hash; - var provider; - - before('init provider', function (done) { - providerInit(function(p) { - provider = p; - web3.setProvider(p); - done(); - }); - }); - - before("Gather accounts", function(done) { - web3.eth.getAccounts(function(err, a) { - if (err) return done(err); - accounts = a; - done(); - }); - }); - - before("send transaction", function (done) { - web3.eth.sendTransaction({ - from: accounts[0], - gas: '0x2fefd8', - data: contract.binary - }, function(err, hash) { - if (err) return done(err); - tx_hash = hash; - done(); - }); - }); - - it("should have block height 1", function (done) { - this.timeout(5000); - web3.eth.getBlockNumber(function(err, res) { - if (err) return done(err); - - assert(res == 1); - - // Close the first provider now that we've gotten where we need to be. - // Note: we specifically close the provider so we can read from the same db. - provider.close(done); - }); - }); - - it("should reopen the provider", function (done) { - providerInit(function(p) { - provider = p; - web3.setProvider(provider); - done(); - }); - }); - - it("should still be on block height 1", function (done) { - this.timeout(5000); - web3.eth.getBlockNumber(function(err, result) { - if (err) return done(err); - assert(result == 1); - done(); - }); - }); - - it("should still have block data for first block", function (done) { - web3.eth.getBlock(1, function(err, result) { - if (err) return done(err); - done(); - }); - }); - - it("should have a receipt for the previous transaction", function(done) { - web3.eth.getTransactionReceipt(tx_hash, function(err, receipt) { - if (err) return done(err); - - assert.notEqual(receipt, null, "Receipt shouldn't be null!"); - assert.equal(receipt.transactionHash, tx_hash); - done(); - }) - }); - - it("should maintain the balance of the original accounts", function (done) { - web3.eth.getBalance(accounts[0], function(err, balance) { - if (err) return done(err); - assert(balance > 98); - done(); - }); - }); - - }); -} - -var mnemonic = "debris electric learn dove warrior grow pistol carry either curve radio hidden"; - -describe("Default DB", function() { - var dbPath = temp.mkdirSync('testrpc-db-'); - // initialize a persistent provider - - var providerInit = function(cb) { - provider = Ganache.provider({ - db_path: dbPath, - mnemonic - }); - - cb(provider); - } - - runTests(providerInit); - -}); - -describe("Custom DB", function() { - var db = memdown(); - - // initialize a custom persistence provider - var providerInit = function(cb) { - provider = Ganache.provider({ - db, - mnemonic - }); - - cb(provider); - } - - runTests(providerInit); - -}); diff --git a/test/public-exports.js b/test/public-exports.js deleted file mode 100644 index e2103ef8fc..0000000000 --- a/test/public-exports.js +++ /dev/null @@ -1,8 +0,0 @@ -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require("assert"); - -describe("BuildType", function() { - it("Tests that we are using the right version", () =>{ - assert(process.env.TEST_BUILD ? Ganache._webpacked === true : Ganache._webpacked === false); - }); -}); \ No newline at end of file diff --git a/test/requests.js b/test/requests.js deleted file mode 100644 index 4b9ecc88aa..0000000000 --- a/test/requests.js +++ /dev/null @@ -1,1523 +0,0 @@ -var Web3 = require('web3'); -var Web3WsProvider = require('web3-providers-ws'); -var Transaction = require('ethereumjs-tx'); -var utils = require('ethereumjs-util'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var solc = require("solc"); -var fs = require("fs"); -var to = require("../lib/utils/to"); -var _ = require("lodash"); - -var source = fs.readFileSync("./test/Example.sol", {encoding: "utf8"}); -var result = solc.compile(source, 1); -var secretKeys = [ - '0xda09f8cdec20b7c8334ce05b27e6797bef01c1ad79c59381666467552c5012e3', - '0x0d14f32c8e3ed7417fb7db52ebab63572bf7cfcd557351d4ccf19a05edeecfa5', - '0x0d80aca78bfaf3ab47865a53e5977e285c41c028a15313f917fe78abe5a50ef7', - '0x00af8067d4c69abca7234194f154d7f31e13c0e53dae9260432f1bcc6d1d13fb', - '0x8939a6a37b48c47f9bc683c371dd96e819d65f6138f3b376a622ecb40379bd22', - '0x4a3665bf95efd38cb9820ce129a26fee03927f17930924c98908c8885ca53606', - '0x111bd4b380f2eeb0d00b025d574908d59c1bfa0030d7a69f69445c171d8cfa27', - '0x6aff34e843c3a99fe21dcc014e3b5bf6a160a4bb8c4c470ea79acd33d9bea41f', - '0x12ae0eb585babc60c88a74190a6074488a0d2f296124ce37f85dbec1d693906f', - '0xd46dc75904628a0b0eaffdda6acbe2687924299995708e30d05a1e8a2a1c5d45' -]; - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - - -// Note: Certain properties of the following contract data are hardcoded to -// maintain repeatable tests. If you significantly change the solidity code, -// make sure to update the resulting contract data with the correct values. -var contract = { - solidity: source, - abi: result.contracts[":Example"].interface, - binary: "0x" + result.contracts[":Example"].bytecode, - runtimeBinary: '0x' + result.contracts[":Example"].runtimeBytecode, - position_of_value: "0x0000000000000000000000000000000000000000000000000000000000000000", - expected_default_value: 5, - call_data: { - gasPrice: '0x01', // This is important, as passing it has exposed errors in the past. - to: null, // set by test - data: '0x3fa4f245' - }, - transaction_data: { - from: null, // set by test - to: null, // set by test - data: '0x552410770000000000000000000000000000000000000000000000000000000000000019', // sets value to 25 (base 10) - gas: 3141592 - } -}; - -var tests = function(web3) { - var accounts; - var personalAccount; - - before('create and fund personal account', function() { - return web3.eth.getAccounts() - .then(function(accs) { - - accounts = accs.map(function(val) { - return val.toLowerCase(); - }); - - return web3.eth.personal.newAccount("password") - }).then(function(acct) { - personalAccount = acct - }) - }); - - describe("eth_accounts", function() { - it("should return 10 addresses", function(done) { - assert.deepEqual(accounts.length, 10); - done(); - }); - }); - - describe("eth_getCompilers", function() { - it("should return an empty array", function() { - return web3.eth.getCompilers() - .then(function(compilers) { - assert(Array.isArray(compilers)); - assert.equal(0, compilers.length); - }) - }); - }); - - describe("eth_blockNumber", function() { - it("should return initial block number of zero", function(done) { - var number = web3.eth.getBlockNumber(function(err, result) { - if (err) return done(err); - - assert.deepEqual(result, 0); - done(); - }); - - // Note: We'll assert the block number changes on transactions. - }); - }); - - describe("eth_coinbase", function() { - it("should return correct address", function(done) { - web3.eth.getCoinbase(function(err, coinbase) { - if (err) return done(err); - - assert.equal(coinbase, accounts[0]); - done(); - }); - }); - }); - - describe("eth_mining", function() { - it("should return true", function(done) { - web3.eth.isMining(function(err, result) { - if (err) return done(err); - - assert.deepEqual(result, true); - done(); - }); - }); - }); - - describe("eth_hashrate", function() { - it("should return hashrate of zero", function(done) { - web3.eth.getHashrate(function(err, result) { - if (err) return done(err); - - assert.deepEqual(result, 0); - done(); - }); - }); - }); - - describe("eth_gasPrice", function() { - it("should return gas price of 2 gwei", function(done) { - web3.eth.getGasPrice(function(err, result) { - if (err) return done(err); - - assert.equal(to.hexWithZeroPadding(result), to.hexWithZeroPadding(2000000000)); - done(); - }); - }); - }); - - describe("eth_getBalance", function() { - it("should return initial balance", function(done) { - web3.eth.getBalance(accounts[0], function(err, result) { - if (err) return done(err); - - assert.deepEqual(result, "100000000000000000000"); - done(); - }); - }); - - it("should return 0 for non-existent account", function(done) { - web3.eth.getBalance("0x1234567890123456789012345678901234567890", function(err, result) { - if (err) return done(err); - - assert.equal("0x" + result.toString(16), "0x0"); - done(); - }); - }); - }); - - describe("eth_getBlockByNumber", function() { - it("should return block given the block number", function(done) { - web3.eth.getBlock(0, true, function(err, block) { - if (err) return done(err); - - var expectedFirstBlock = { - number: 0, - hash: block.hash, // Don't test this one - mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000", - parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', - nonce: '0x0000000000000000', - sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', - stateRoot: '0x7caba99698b405652a6bcb1038efa16db54b3338af71fa832a0b99a3e6c344bc', - receiptsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', - miner: '0x0000000000000000000000000000000000000000', - difficulty: "0", - totalDifficulty: "0", - extraData: '0x', - size: 1000, - gasLimit: 6721975, - gasUsed: 0, - timestamp: block.timestamp, // Don't test this one. - transactions: [], - uncles: [] - }; - - assert.deepEqual(block, expectedFirstBlock); - - var now = (new Date()).getTime(); - var then = block.timestamp * 1000; // block.timestamp is in seconds. - - assert.equal(then.toString().length, now.toString().length, "Invalid timestamp length"); - assert(then < now, "Time returned was greater than the current time"); - done(); - }); - }); - - it("should return null given a future block number", function(done) { - web3.eth.getBlock(10000, true, function(err, block) { - if (err) return done(err); - - assert.deepEqual(block, null); - done(); - }); - }); - - it("should return transactions in the block as well", function(done) { - web3.eth.sendTransaction({ - from: accounts[0], - data: contract.binary, - gas: 3141592 - }, function(err, tx_hash) { - if (err) return done(err); - - // Assume it was processed correctly. - assert.deepEqual(tx_hash.length, 66); - - web3.eth.getBlock("latest", true, function(err, block) { - if (err) return done(err); - - assert.equal(block.transactions.length, 1, "Latest block should have one transaction"); - assert.equal(block.transactions[0].hash, tx_hash, "Transaction hashes don't match"); - - //Retest, with transaction only as hash - web3.eth.getBlock("latest", false, function(err, block) { - if (err) return done(err); - - assert.equal(block.transactions.length, 1, "Latest block should have one transaction"); - assert.equal(block.transactions[0], tx_hash, "Transaction hashes don't match"); - - done() - }); - }); - }); - }); - }); - - // Relies on the validity of eth_getBlockByNumber above. - describe("eth_getBlockByHash", function() { - it("should return block given the block hash", function(done) { - web3.eth.getBlock(0, true, function(err, blockByNumber) { - if (err) return done(err); - - web3.eth.getBlock(blockByNumber.hash, true, function(err, blockByHash) { - if (err) return done(err); - - assert.deepEqual(blockByHash, blockByNumber); - done(); - }); - }); - }); - }); - - describe("eth_getBlockTransactionCountByNumber", function(){ - it("should return the number of transactions given the block number (0 transactions)", function(done) { - //Block 0 should have 0 transactions as per test eth_getBlockByNumber - web3.eth.getBlock(0, true, function(err, block) { - if (err) return done(err); - web3.eth.getBlockTransactionCount(0, function(err, blockTransactionCount) { - assert.equal(block.transactions.length, blockTransactionCount, "Block transaction count should be 0."); - assert.equal(0, blockTransactionCount, "Block transaction count should be 0."); - done(); - }); - }); - }); - - it("should return the number of transactions given the block number (1 transaction)", function(done) { - // Create a transaction and check - // Account 0 seems to be running out of gas before all tests are complete - var payingAccount = 2; - - web3.eth.sendTransaction({ - from: accounts[payingAccount], - data: contract.binary, - gas: 3141592 - }, function(err, tx_hash) { - if (err) return done(err); - // Assume it was processed correctly. - assert.deepEqual(tx_hash.length, 66); - - web3.eth.getBlock("latest", true, function(err, block) { - if (err) return done(err); - web3.eth.getBlockTransactionCount(block.number , function(err, blockTransactionCount) { - if (err) return done(err); - assert.equal(block.transactions.length, blockTransactionCount, "Block transaction count should be 1."); - assert.equal(1, blockTransactionCount, "Block transaction count should be 1."); - done(); - }); - }); - }); - }); - - it("should return 0 transactions when the block doesn't exist", function(done) { - web3.eth.getBlockTransactionCount(1000000, function(err, blockTransactionCount) { - if (err) return done(err); - assert.equal(0, blockTransactionCount, "Block transaction count should be 0."); - done(); - }); - }); - }); - - // Dependent upon validity of eth_getBlockTransactionCountByNumber - describe("eth_getBlockTransactionCountByHash", function(){ - it("should return the number of transactions given the hash", function(done) { - web3.eth.getBlock(0, true, function(err, blockByNumber) { - if (err) return done(err); - web3.eth.getBlockTransactionCount(blockByNumber.number, true, function(err, txCountByHash) { - if (err) return done(err); - web3.eth.getBlockTransactionCount(blockByNumber.hash , function(err, txCountByNumber) { - if (err) return done(err); - assert.equal(txCountByHash, txCountByNumber, "Txn count for block retrieved by hash should equal count retrieved by number."); - done(); - }); - }); - }); - }); - }); - - describe("eth_getCode", function() { - it("should return 0x for eth_getCode called on a non-contract", function(done) { - web3.eth.getCode("0x000000000000000000000000000000000000dEaD", function(err, code) { - assert.equal(code, "0x"); - done(); - }); - }); - }); - - describe("eth_sign", function() { - var accounts; - var signingWeb3; - - // This account produces an edge case signature when it signs the hex-encoded buffer: - // '0x07091653daf94aafce9acf09e22dbde1ddf77f740f9844ac1f0ab790334f0627'. (See Issue #190) - var acc = { - balance: "0x00", - secretKey: "0xe6d66f02cd45a13982b99a5abf3deab1f67cf7be9fee62f0a072cb70896342e4" - }; - - // Load account. - before(function( done ){ - signingWeb3 = new Web3(); - signingWeb3.setProvider(Ganache.provider({ - accounts: [ acc ] - })); - signingWeb3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs.map(function(val) { - return val.toLowerCase(); - }); - done(); - }); - }); - - it("should produce a signature whose signer can be recovered", function() { - var msg = utils.toBuffer("asparagus"); - var msgHash = utils.hashPersonalMessage(msg); - - return signingWeb3.eth.sign(utils.bufferToHex(msg), accounts[0]).then(sgn => { - sgn = utils.stripHexPrefix(sgn); - var r = Buffer.from(sgn.slice(0, 64), 'hex'); - var s = Buffer.from(sgn.slice(64, 128), 'hex'); - var v = parseInt(sgn.slice(128, 130), 16) + 27; - var pub = utils.ecrecover(msgHash, v, r, s); - var addr = utils.setLength(utils.fromSigned(utils.pubToAddress(pub)), 20); - addr = to.hex(addr); - assert.deepEqual(addr, accounts[0]); - }); - }); - - it("should work if ecsign produces 'r' or 's' components that start with 0", function() { - // This message produces a zero prefixed 'r' component when signed by ecsign - // w/ the account set in this test's 'before' block. - var msgHex = '0x07091653daf94aafce9acf09e22dbde1ddf77f740f9844ac1f0ab790334f0627'; - var edgeCaseMsg = utils.toBuffer(msgHex); - var msgHash = utils.hashPersonalMessage(edgeCaseMsg); - return signingWeb3.eth.sign(msgHex, accounts[0]).then(sgn => { - sgn = utils.stripHexPrefix(sgn); - var r = Buffer.from(sgn.slice(0, 64), 'hex'); - var s = Buffer.from(sgn.slice(64, 128), 'hex'); - var v = parseInt(sgn.slice(128, 130), 16) + 27; - var pub = utils.ecrecover(msgHash, v, r, s); - var addr = utils.setLength(utils.fromSigned(utils.pubToAddress(pub)), 20); - addr = to.hex(addr); - assert.deepEqual(addr, accounts[0]); - }); - }) - - after("shutdown", function(done) { - let provider = signingWeb3._provider; - signingWeb3.setProvider() - provider.close(done) - }); - - }); - - describe("eth_signTypedData", function() { - var accounts; - var signingWeb3; - - // Account based on https://github.com/ethereum/EIPs/blob/master/assets/eip-712/Example.js - var acc = { - balance: "0x00", - secretKey: web3.utils.sha3('cow') - }; - - // Load account. - before(function( done ){ - signingWeb3 = new Web3(); - signingWeb3.setProvider(Ganache.provider({ - accounts: [ acc ] - })); - signingWeb3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs.map(function(val) { - return val.toLowerCase(); - }); - done(); - }); - }); - - it("should produce a signature whose signer can be recovered", function(done) { - var typedData = {"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Person":[{"name":"name","type":"string"},{"name":"wallet","type":"address"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person"},{"name":"contents","type":"string"}]},"primaryType":"Mail","domain":{"name":"Ether Mail","version":"1","chainId":1,"verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"},"message":{"from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"},"contents":"Hello, Bob!"}} - var msg = utils.toBuffer("asparagus"); - var msgHash = utils.hashPersonalMessage(msg); - - signingWeb3.currentProvider.sendAsync({ - jsonrpc: "2.0", - method: "eth_signTypedData", - params: [accounts[0], typedData], - id: new Date().getTime() - }, function(err, response) { - if (err) { - return done(err); - } - console.log(response); - assert.equal(response.result, "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c"); - done(); - }); - }); - - after("shutdown", function(done) { - let provider = signingWeb3._provider; - signingWeb3.setProvider() - provider.close(done) - }); - - }); - - describe('eth_sendTransaction', () => { - - it("should fail with bad nonce (too low)", function(done) { - var transaction = { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x00", // too low nonce - } - - web3.eth.sendTransaction(transaction, function(err, result) { - assert(err.message.indexOf("the tx doesn't have the correct nonce. account has nonce of: 1 tx has nonce of: 0") >= 0, `Incorrect error message: ${err.message}`); - done() - }) - - }); - - it("should fail with bad nonce (too high)", function(done) { - var transaction = { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0xff", // too high nonce - } - - web3.eth.sendTransaction(transaction, function(err, result) { - assert(err.message.indexOf("the tx doesn't have the correct nonce. account has nonce of: 1 tx has nonce of: 255") >= 0); - done() - }); - - }); - - it("should succeed with right nonce (1)", function(done) { - var transaction = { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x01" - } - - web3.eth.sendTransaction(transaction, function(err, result) { - done(err) - }) - - }) - - it("should fail with bad nonce (skipped value)", function(done) { - let tempWeb3 = new Web3(Ganache.provider({ - blockTime: .5, // seconds - mnemonic: "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat" - })); - - const accounts = [ // configured with mnemonic - '0x627306090abab3a6e1400e9345bc60c78a8bef57', - '0xf17f52151ebef6c7334fad080c5704d77216b732', - ]; - const secretKeys = [ // configured with mnemonic - '0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3' - ]; - - let transaction = { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x00" - } - - let transaction2 = { - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x02" // Skipped nonce 1 - } - - tempWeb3.eth.sendTransaction(transaction, function(err, hash) { - if (err) return done(err); - // Ensure there's no receipt since the transaction hasn't yet been processed. - tempWeb3.eth.getTransactionReceipt(hash, function(err, receipt) { - if (err) return done(err); - assert.equal(receipt, null, "No receipt since the transaction hasn't yet been processed."); - // Issue second transaction - tempWeb3.eth.sendTransaction(transaction2, function(err2, hash2) { - assert.notDeepEqual(err2, null, 'Incorrect nonce, tx should fail.'); - setTimeout(function() { - // Wait .75 seconds (1.5x the mining interval) then get the receipt. It should be processed. - tempWeb3.eth.getTransactionReceipt(hash, function(err3, receipt1) { - assert.notDeepEqual(receipt1, null, 'First tx should be processed'); - done() - }); - }, 750); - }); - }); - }); - }) - }) - - describe('eth_sendRawTransaction', () => { - - it("should fail with bad nonce (too low)", function(done) { - var transaction = new Transaction({ - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x00", // too low nonce - }) - - var secretKeyBuffer = Buffer.from(secretKeys[0].substr(2), 'hex') - transaction.sign(secretKeyBuffer) - - web3.eth.sendSignedTransaction(transaction.serialize(), function(err, result) { - assert(err.message.indexOf("the tx doesn't have the correct nonce. account has nonce of: 2 tx has nonce of: 0") >= 0, `Incorrect error message: ${err.message}`); - done() - }) - - }) - - it("should fail with bad nonce (too high)", function(done) { - var transaction = new Transaction({ - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0xff", // too high nonce - }) - - var secretKeyBuffer = Buffer.from(secretKeys[0].substr(2), 'hex') - transaction.sign(secretKeyBuffer) - - web3.eth.sendSignedTransaction(transaction.serialize(), function(err, result) { - assert(err.message.indexOf("the tx doesn't have the correct nonce. account has nonce of: 2 tx has nonce of: 255") >= 0); - done() - }) - - }) - - it("should succeed with right nonce (1)", function(done) { - var transaction = new Transaction({ - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x02" - }) - - var secretKeyBuffer = Buffer.from(secretKeys[0].substr(2), 'hex') - transaction.sign(secretKeyBuffer) - - web3.eth.sendSignedTransaction(transaction.serialize(), function(err, result) { - done(err) - }) - }) - - it("should fail with bad nonce (skipped value)", function(done) { - let tempWeb3 = new Web3(Ganache.provider({ - blockTime: .5, // seconds - mnemonic: "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat" - })); - - const accounts = [ // configured with mnemonic - '0x627306090abab3a6e1400e9345bc60c78a8bef57', - '0xf17f52151ebef6c7334fad080c5704d77216b732', - ]; - const secretKeys = [ // configured with mnemonic - '0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3' - ]; - - let transaction = new Transaction({ - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x00" - }) - let transaction2 = new Transaction({ - "value": "0x10000000", - "gasLimit": "0x33450", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x02" // Skipped nonce 1 - }) - - let secretKeyBuffer = Buffer.from(secretKeys[0].substr(2), 'hex') - transaction.sign(secretKeyBuffer) - transaction2.sign(secretKeyBuffer) - - - tempWeb3.eth.sendSignedTransaction(transaction.serialize(), function(err, tx) { - if (err) return done(err); - // Ensure there's no receipt since the transaction hasn't yet been processed. - tempWeb3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - assert.equal(receipt, null, "No receipt since the transaction hasn't yet been processed."); - // Issue second transaction - tempWeb3.eth.sendSignedTransaction(transaction2.serialize(), function(err2, tx2) { - assert.notDeepEqual(err2, null, 'Incorrect nonce, tx should fail.'); - setTimeout(function() { - // Wait .75 seconds (1.5x the mining interval) then get the receipt. It should be processed. - tempWeb3.eth.getTransactionReceipt(tx, function(err3, receipt1) { - assert.notDeepEqual(receipt1, null, 'First tx should be processed'); - done() - }); - }, 750); - }); - }); - }); - }) - - - it("should respond with correct txn hash", function(done) { - var provider = web3.currentProvider; - var transaction = new Transaction({ - "value": "0x00", - "gasLimit": "0x5208", - "from": accounts[0], - "to": accounts[1], - "nonce": "0x03" - }) - - var secretKeyBuffer = Buffer.from(secretKeys[0].substr(2), 'hex') - transaction.sign(secretKeyBuffer) - - web3.eth.sendSignedTransaction(transaction.serialize(), function(err, result) { - assert.equal(result, to.hex(transaction.hash())) - done(err) - }) - }) - }) - - describe("contract scenario", function() { - - // These are expected to be run in order. - var initialTransaction; - var contractAddress; - var contractCreationBlockNumber; - - it("should add a contract to the network (eth_sendTransaction)", function(done) { - web3.eth.sendTransaction({ - from: accounts[0], - data: contract.binary, - gas: 3141592, - value: 1 - }, function(err, hash) { - if (err) return done(err); - - assert.deepEqual(hash.length, 66); - initialTransaction = hash - web3.eth.getTransactionReceipt(hash, function(err, receipt) { - if (err) return done(err); - contractCreationBlockNumber = receipt.blockNumber; // For defaultBlock test - assert(receipt) - done(); - }) - }); - }); - - it("should verify the transaction immediately (eth_getTransactionReceipt)", function(done) { - web3.eth.getTransactionReceipt(initialTransaction, function(err, receipt) { - if (err) return done(err); - - contractAddress = receipt.contractAddress; - - assert.notEqual(receipt, null, "Transaction receipt shouldn't be null"); - assert.notEqual(contractAddress, null, "Transaction did not create a contract"); - done(); - }); - }); - - it("should return null if asked for a receipt for a nonexistent transaction (eth_getTransactionReceipt)", function(done) { - web3.eth.getTransactionReceipt("0xdeadbeef", function(err, receipt) { - if (err) return done(err); - - assert.equal(receipt, null, "Transaction receipt should be null"); - done(); - }); - }); - - it("should verify the code at the address matches the runtimeBinary (eth_getCode)", function(done) { - web3.eth.getCode(contractAddress, function(err, result) { - if (err) return done(err); - assert.equal(result, contract.runtimeBinary); - done(); - }); - }); - - it("should have balance of 1 (eth_getBalance)", function(done) { - web3.eth.getBalance(contractAddress, function(err, result) { - if (err) return done(err); - assert.equal(result, 1); - done(); - }); - }); - - it("should be able to read data via a call (eth_call)", function(done) { - var call_data = contract.call_data; - call_data.to = contractAddress; - call_data.from = accounts[0]; - - var starting_block_number = null; - - // TODO: Removing this callback hell would be nice. - web3.eth.getBlockNumber(function(err, result) { - if (err) return done(err); - - starting_block_number = result; - - web3.eth.call(call_data, function(err, result) { - if (err) return done(err); - assert.equal(to.number(result), 5); - - web3.eth.getBlockNumber(function(err, result) { - if (err) return done(err); - - assert.equal(result, starting_block_number, "eth_call increased block count when it shouldn't have"); - done(); - }); - }); - }); - }); - - it("should get back a runtime error on a bad call (eth_call)", function(done) { - var call_data = _.cloneDeep(contract.call_data); - call_data.to = contractAddress; - call_data.from = accounts[0]; - - // TODO: Removing this callback hell would be nice. - web3.eth.estimateGas(call_data, function (err, result) { - if (err) return done(err); - // set a low gas limit to force a runtime error - call_data.gas = result - 1; - - web3.eth.call(call_data, function (err, result) { - // should have received an error - assert(err, "did not return runtime error"); - assert(/.*out of gas.*/.test(err.message), `Did not receive an 'out of gas' error. got '${err.message}' instead.`) - done(); - }); - }); - }); - - it("should be able to make a call from an address not in the accounts list (eth_call)", function(done) { - var from = "0x1234567890123456789012345678901234567890"; - - // Assert precondition: Ensure from address isn't in the accounts list. - accounts.forEach(function(account) { - assert.notEqual(from, account, "Test preconditions not met: from address must not be within the accounts list, please rerun"); - }); - - var call_data = contract.call_data; - call_data.to = contractAddress; - call_data.from = from; - - web3.eth.call(call_data, function(err, result) { - if (err) return done(err); - assert.equal(to.number(result), 5); - - done(); - }); - }); - - it("should be able to make a call when no address is listed (eth_call)", function(done) { - var call_data = contract.call_data; - call_data.to = contractAddress; - delete call_data.from; - - web3.eth.call(call_data, function(err, result) { - if (err) return done(err); - assert.equal(to.number(result), 5); - - done(); - }); - }); - - it("should represent the block number correctly in the Oracle contract (oracle.blockhash0)", function(done){ - var oracleSol = fs.readFileSync("./test/Oracle.sol", {encoding: "utf8"}); - var oracleOutput = solc.compile(oracleSol).contracts[":Oracle"] - web3.eth.personal.unlockAccount(accounts[0], "password", function(err, result) { - var contract = new web3.eth.Contract(JSON.parse(oracleOutput.interface)); - contract.deploy({ - data: oracleOutput.bytecode, - }).send({ - from: accounts[0], - gas: 3141592 - }).then(function(oracle) { - // TODO: ugly workaround - not sure why this is necessary. - if (!oracle._requestManager.provider) { - oracle._requestManager.setProvider(web3.eth._provider); - } - web3.eth.getBlock(0, true, function(err, block){ - if (err) return done(err) - oracle.methods.blockhash0().call(function(err, blockhash){ - if (err) return done(err) - assert.equal(blockhash, block.hash); - done() - }); - }); - }); - }); - }); - - it("should be able to estimate gas of a transaction (eth_estimateGas)", function(done){ - var tx_data = contract.transaction_data; - tx_data.to = contractAddress; - tx_data.from = accounts[0]; - - var starting_block_number = null; - - // TODO: Removing this callback hell would be nice. - web3.eth.getBlockNumber(function(err, result) { - if (err) return done(err); - - starting_block_number = result; - - web3.eth.estimateGas(tx_data, function(err, result) { - if (err) return done(err); - assert.equal(result, 27693); - - web3.eth.getBlockNumber(function(err, result) { - if (err) return done(err); - - assert.equal(result, starting_block_number, "eth_estimateGas increased block count when it shouldn't have"); - done(); - }); - }); - }); - }); - - it("should be able to estimate gas from an account not within the accounts list (eth_estimateGas)", function(done){ - var tx_data = contract.transaction_data; - tx_data.to = contractAddress; - tx_data.from = "0x1234567890123456789012345678901234567890";; - - var starting_block_number = null; - - web3.eth.estimateGas(tx_data, function(err, result) { - if (err) return done(err); - assert.equal(result, 27693); - done(); - }); - }); - - it("should be able to estimate gas when no account is listed (eth_estimateGas)", function(done){ - var tx_data = contract.transaction_data; - tx_data.to = contractAddress; - delete tx_data.from; - - var starting_block_number = null; - - web3.eth.estimateGas(tx_data, function(err, result) { - if (err) return done(err); - assert.equal(result, 27693); - done(); - }); - }); - - it("should be able to send a state changing transaction (eth_sendTransaction)", function(done) { - var tx_data = contract.transaction_data; - tx_data.to = contractAddress; - tx_data.from = accounts[0]; - - var call_data = contract.call_data; - call_data.from = accounts[0]; - call_data.to = contractAddress; - - web3.eth.sendTransaction(tx_data, function(err, tx) { - if (err) return done(err); - // Now double check the data was set properly. - // NOTE: Because ethereumjs-testrpc processes transactions immediately, - // we can do this. Calling the call immediately after the transaction would - // fail on a different Ethereum client. - - web3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - - assert.equal(receipt.logs.length, 1, "Receipt had wrong amount of logs"); - assert.equal(receipt.logs[0].blockHash, receipt.blockHash, "Logs blockhash doesn't match block blockhash"); - - //console.log(call_data); - web3.eth.call(call_data, function(err, result) { - if (err) return done(err); - - assert.equal(to.number(result), 25); - done(); - }); - }); - }); - }); - - // NB: relies on the previous test setting value to 25 and the contract deployment setting - // original value to 5. `contractCreationBlockNumber` is set in the first test of this - // describe block. - it("should read data via a call at a specified blockNumber (eth_call)", function(done){ - var startingBlockNumber = null; - var call_data = contract.call_data; - - web3.eth.getBlockNumber().then(function(result){ - - startingBlockNumber = result; - return web3.eth.call(call_data) - - }).then(function(result){ - - assert.equal(to.number(result), 25, "value retrieved from latest block should be 25"); - return web3.eth.call(call_data, contractCreationBlockNumber) - - }).then(function(result){ - - assert.equal(to.number(result), 5, "value retrieved from contract creation block should be 5"); - return web3.eth.getBlockNumber() - - }).then(function(result){ - - assert.equal(result, startingBlockNumber, "eth_call w/defaultBlock increased block count"); - return web3.eth.call(call_data); - - }).then(function(result){ - - assert.equal(to.number(result), 25, "stateTrie root was corrupted by defaultBlock call"); - done(); - }); - }); - - it('should read data via a call when specified blockNumber is "earliest" (eth_call)', function(done) { - var call_data = contract.call_data; - - web3.eth.call(call_data, "earliest").then(function(result){ - assert.equal(to.number(result), 0, "value retrieved from earliest block should be zero"); - done(); - }) - }); - - it('should read data via a call when specified blockNumber is "pending" (eth_call)', function(done){ - var call_data = contract.call_data; - - web3.eth.call(call_data, "pending").then(function(result){ - assert.equal(to.number(result), 25, "value retrieved from pending block should be 25"); - done(); - }); - }); - - it("should error when reading data via a call at a non-existent blockNumber (eth_call)", function(done){ - var nonExistentBlock; - var call_data = contract.call_data; - - web3.eth.getBlockNumber().then(function(result){ - - nonExistentBlock = result + 1; - return web3.eth.call(call_data, nonExistentBlock); - - }).then(function(result){ - assert.fail(); - - }).catch(function(error){ - - assert(error.message.includes('index out of range')); - assert(error.message.includes(nonExistentBlock)); - done(); - }); - }); - - it("should only be able to send an unsigned state changing transaction from an address within the accounts list (eth_sendTransaction)", function(done) { - var badAddress = "0x1234567890123456789012345678901234567890"; - - var tx_data = {}; - tx_data.to = "0x1111111111000000000011111111110000000000"; - tx_data.from = badAddress; - tx_data.value = "0x1"; - - web3.eth.sendTransaction(tx_data, function(err, result) { - if (err) { - assert(/sender account not recognized/.test(err.message), `Expected error message containing 'sender account not recognized', but got ${err.message}`) - done(); - } else { - assert.fail("Should have received an error") - } - }); - }); - - it("should get the data from storage (eth_getStorageAt) with padded hex", function(done) { - web3.eth.getStorageAt(contractAddress, contract.position_of_value, function(err, result) { - assert.equal(to.number(result), 25); - done(); - }); - }); - - it("should get the data from storage (eth_getStorageAt) with unpadded hex", function(done) { - web3.eth.getStorageAt(contractAddress, '0x0', function(err, result) { - assert.equal(to.number(result), 25); - done(); - }); - }); - - it("should get the data from storage (eth_getStorageAt) with number", function(done) { - web3.eth.getStorageAt(contractAddress, 0, function(err, result) { - assert.equal(to.number(result), 25); - done(); - }); - }); - - }); - - describe("contract scenario (raw tx)", function() { - - var tx = new Transaction({ - data: contract.binary, - gasLimit: to.hex(3141592) - }) - var privateKey = Buffer.from('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex') - var senderAddress = '0x'+utils.privateToAddress(privateKey).toString('hex') - tx.sign(privateKey) - var rawTx = '0x'+tx.serialize().toString('hex') - - // These are expected to be run in order. - var initialTransaction; - var blockHash; - var blockNumber; - var contractAddress; - - it("should first populate senders address", function(done) { - // populate senders balance - web3.eth.sendTransaction({ - from: accounts[0], - to: senderAddress, - value: '0x3141592', - gas: 3141592 - }, function(err, hash) { - if (err) return done(err); - web3.eth.getTransactionReceipt(hash, function(err, receipt) { - if (err) return done(err) - assert(receipt); - done(); - }) - }); - }); - - it("should add a contract to the network (eth_sendRawTransaction)", function(done) { - web3.eth.sendSignedTransaction(rawTx, function(err, result) { - if (err) return done(err); - initialTransaction = result; - done(); - }); - }); - - it("should verify the transaction immediately (eth_getTransactionReceipt)", function(done) { - web3.eth.getTransactionReceipt(initialTransaction, function(err, receipt) { - if (err) return done(err); - - contractAddress = receipt.contractAddress; - blockHash = receipt.blockHash; - blockNumber = receipt.blockNumber; - - assert.notEqual(receipt, null, "Transaction receipt shouldn't be null"); - assert.notEqual(contractAddress, null, "Transaction did not create a contract"); - assert.equal(receipt.hasOwnProperty('v'), true, "Transaction includes v signature parameter"); - assert.equal(receipt.hasOwnProperty('r'), true, "Transaction includes r signature parameter"); - assert.equal(receipt.hasOwnProperty('s'), true, "Transaction includes s signature parameter"); - done(); - }); - }); - - it("should verify the transaction immediately (eth_getTransactionByHash)", function(done) { - web3.eth.getTransaction(initialTransaction, function(err, result) { - if (err) return done(err); - - assert.notEqual(result, null, "Transaction result shouldn't be null"); - assert.equal(result.hash, initialTransaction, "Resultant hash isn't what we expected") - assert.equal(result.hasOwnProperty('v'), true, "Transaction includes v signature parameter"); - assert.equal(result.hasOwnProperty('r'), true, "Transaction includes r signature parameter"); - assert.equal(result.hasOwnProperty('s'), true, "Transaction includes s signature parameter"); - done(); - }); - }); - - it("should return null if transaction doesn't exist (eth_getTransactionByHash)", function(done) { - web3.eth.getTransaction("0x401b8ebb563ec9425b052aba8896cb74e07635563111b5a0663289d1baa8eb12", function(err, result) { - if (err) return done(err); - - assert.equal(result, null, "Receipt should be null"); - - done(); - }); - }); - - it("should verify there's code at the address (eth_getCode)", function(done) { - web3.eth.getCode(contractAddress, function(err, result) { - if (err) return done(err); - assert.notEqual(result, null); - assert.notEqual(result, "0x"); - - // NOTE: We can't test the code returned is correct because the results - // of getCode() are *supposed* to be different than the code that was - // added to the chain. - - done(); - }); - }); - - it("should be able to get the transaction from the block (eth_getTransactionByBlockHashAndIndex)", function(done) { - web3.eth.getTransactionFromBlock(blockHash, 0, function(err, result) { - if (err) return done(err); - - assert.equal(result.hash, initialTransaction); - assert.equal(result.blockNumber, blockNumber); - assert.equal(result.blockHash, blockHash); - done(); - }); - }); - - it("should return null if block doesn't exist (eth_getTransactionByBlockHashAndIndex)", function(done) { - var badBlockHash = "0xaaaaaaeb03ec5e3c000d150df2c9e7ffc31e728d12aaaedc5f6cccaca5aaaaaa"; - web3.eth.getTransactionFromBlock(badBlockHash, 0, function(err, result) { - if (err) return done(err); - - assert.equal(result, null); - - done(); - }); - }); - - it("should be able to get the transaction from the block (eth_getTransactionByBlockNumberAndIndex)", function(done) { - web3.eth.getTransactionFromBlock(blockNumber, 0, function(err, result) { - if (err) return done(err); - - assert.equal(result.hash, initialTransaction); - assert.equal(result.blockNumber, blockNumber); - assert.equal(result.blockHash, blockHash); - done(); - }); - }); - - it("should throw error for transactions that don't exist in block (eth_getTransactionByBlockNumberAndIndex)", function(done) { - web3.eth.getTransactionFromBlock(blockNumber, 3, function(err, result) { - // We want an error because there is no transaction with id 3. - if (err) return done(); - - done(new Error("We didn't receive an error like we expected")); - }); - }); - }); - - describe("eth_getTransactionCount", function() { - it("should return 0 for non-existent account", function(done) { - web3.eth.getTransactionCount("0x1234567890123456789012345678901234567890", function(err, result) { - if (err) return done(err); - - assert.equal(result, "0x0"); - done(); - }); - }); - }); - - describe("eth_getTransactionCount", function() { - it("should error for non-existent block", function(done) { - web3.eth.getTransactionCount("0x1234567890123456789012345678901234567890", 9999999, function(err, result) { - assert(err, "Error with message 'Unknown block number' expected, instead no error was returned"); - assert(err.message.indexOf("Unknown block number") > -1); - done(); - }); - }); - }); - - describe("eth_compileSolidity (not supported)", function() { - this.timeout(5000); - it("correctly compiles solidity code", function(done) { - web3.eth.compile.solidity(source, function(err, result) { - assert(err != null) - assert(err.message.indexOf("Method eth_compileSolidity not supported") >= 0); - done(); - }); - }); - }); - - describe("miner_stop", function(){ - it("should stop mining", function(done){ - web3.currentProvider.send({ - id: new Date().getTime(), - jsonrpc: "2.0", - method: "miner_stop", - }, function(err,result){ - var tx_data = {} - tx_data.to = accounts[1]; - tx_data.from = accounts[0]; - tx_data.value = '0x1'; - - // we don't use web3.eth.sendTransaction here because it gets huffy waiting for a receipt, - // then winds up w/ an unhandled rejection on server.close later on - web3._provider.send({ - id: new Date().getTime(), - jsonrpc: "2.0", - method: "eth_sendTransaction", - params: [tx_data] - }, function(err, result) { - if (err) return done(err); - let tx = result.result - - web3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - - assert.equal(receipt, null); - web3.currentProvider.send({ - id: new Date().getTime(), - jsonrpc: "2.0", - method: "miner_start", - params: [1] - }, function(err, result){ - if (err) return done(err); - done(); - }) - }); - }); - }) - }) - }); - - describe("miner_start", function(){ - it("should start mining", function(done){ - web3.currentProvider.send({ - id: new Date().getTime(), - jsonrpc: "2.0", - method: "miner_stop", - }, function(err,result){ - web3.currentProvider.send({ - id: new Date().getTime(), - jsonrpc: "2.0", - method: "miner_start", - params: [1] - }, function(err,result){ - var tx_data = {} - tx_data.to = accounts[1]; - tx_data.from = accounts[0]; - tx_data.value = 0x1; - - web3.eth.sendTransaction(tx_data, function(err, tx) { - if (err) return done(err); - //Check the receipt - web3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - assert.notEqual(receipt, null); //i.e. receipt exists, so transaction was mined - done(); - }); - }); - }) - }) - }) - - it("should treat the threads argument as optional", function(done){ - web3.currentProvider.send({ - id: new Date().getTime(), - jsonrpc: "2.0", - method: "miner_stop", - }, function(err,result){ - web3.currentProvider.send({ - id: new Date().getTime(), - jsonrpc: "2.0", - method: "miner_start", - params: [] - }, function(err,result){ - var tx_data = {} - tx_data.to = accounts[1]; - tx_data.from = accounts[0]; - tx_data.value = 0x1; - - web3.eth.sendTransaction(tx_data, function(err, tx) { - if (err) return done(err); - //Check the receipt - web3.eth.getTransactionReceipt(tx, function(err, receipt) { - if (err) return done(err); - assert.notEqual(receipt, null); //i.e. receipt exists, so transaction was mined - done(); - }); - }); - }) - }) - }) - }); - - describe("web3_sha3", function() { - it("should hash the given input", function(done) { - var input = "Tim is a swell guy."; - - // web3.sha3() doesn't actually call the function, so we need to call it ourselves. - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "web3_sha3", - params: [input], - id: new Date().getTime() - }, function(err, result) { - if (err) return done(err); - if (result.error) return done(result.error); - - assert.equal(result.result, web3.utils.sha3(input)); - done(); - }) - }); - }); - - describe("net_version", function() { - it("should return a version very close to the current time", function(done) { - web3.eth.net.getId(function(err, result) { - if (err) return done(err); - - var dateAsInt = new Date().getTime() + ""; - var strResult = to.number(result) + ""; - assert.equal(strResult.length, dateAsInt.length, `net_version result, ${result}, doesn't appear to be similar in length the current time as an integer, ${dateAsInt}`) - done(); - }); - }); - }); - - describe("personal_newAccount", function() { - it("should return the new address", function(done) { - web3.eth.personal.newAccount("password", function(err, result) { - if (err) return done(err); - assert.notEqual(result.toLowerCase().match("0x[0-9a-f]{39}"), null, "Invalid address received"); - done(); - }); - }); - }); - - describe("personal_importRawKey", function() { - it("should return the known account address", function(done) { - web3._provider.send({ - jsonrpc: "2.0", - id: 1234, - method: 'personal_importRawKey', - params: ["0x0123456789012345678901234567890123456789012345678901234567890123", "password"] - }, function(err, result) { - if (err) return done(err); - assert.equal(result.result, '0x14791697260e4c9a71f18484c9f997b308e59325', "Raw account not imported correctly"); - done(); - }); - }); - }); - - describe("personal_listAccounts", function() { - it("should return more than 0 accounts", function(done) { - web3.eth.personal.getAccounts(function(err, result) { - if (err) return done(err); - assert.equal(result.length, 13); - done(); - }); - }); - }); - - describe("personal_unlockAccount", function() { - it("should unlock account", function(done) { - web3.eth.personal.unlockAccount(personalAccount, "password", function(err, result) { - if (err) return done(err); - assert.equal(result, true); - done(); - }); - }); - }); - - describe("personal_lockAccount", function() { - it("should lock account", function(done) { - web3.eth.personal.lockAccount(personalAccount, function(err, result) { - if (err) return done(err) - assert.equal(result, true); - done() - }); - }); - }); - - /*describe("personal_sendTransaction", function() { - it("should send transaction", function(done) { - web3.eth.sendTransaction({value: web3.utils.toWei('5', 'ether'), from: accounts[0], to: personalAccount }, function(err, result){ - if (err) return done(err) - - web3.eth.personal.sendTransaction({ - from: personalAccount, - to: accounts[0], - value: 1 - }, "password", function(err, receipt) { - if (err) return done(err); - assert(receipt); - setTimeout(done, 500); - }); - }); - }); - })*/ -} - -var logger = { - log: function(message) { - //console.log(message); - } -}; - -describe("Provider:", function() { - var Web3 = require('web3'); - var web3 = new Web3(); - web3.setProvider(Ganache.provider({ - logger: logger, - seed: "1337", - // so that the runtime errors on call test passes - })); - tests(web3); - - after("shutdown provider", function(done) { - let provider = web3._provider; - web3.setProvider(); - provider.close(done); - }); -}); - -describe("HTTP Server:", function(done) { - var Web3 = require('web3'); - var web3 = new Web3(); - var port = 12345; - var server; - - before("Initialize Ganache server", function(done) { - server = Ganache.server({ - logger: logger, - seed: "1337", - // so that the runtime errors on call test passes - }); - - server.listen(port, function(err) { - web3.setProvider(new Web3.providers.HttpProvider("http://localhost:" + port)); - done(); - }); - }); - - after("Shutdown server", function(done) { - server.close(done); - }); - - tests(web3); -}); - -describe("WebSockets Server:", function(done) { - var Web3 = require('web3'); - var web3 = new Web3(); - var port = 12345; - var server; - - before("Initialize Ganache server", function(done) { - server = Ganache.server({ - logger: logger, - seed: "1337", - // so that the runtime errors on call test passes - }); - server.listen(port, function(err) { - var provider = new Web3WsProvider("ws://localhost:" + port); - var Web3 = require('web3'); - web3.setProvider(provider); - done(); - }); - }); - - tests(web3); - - after("Shutdown server", function(done) { - let provider = web3._provider - web3.setProvider() - provider.connection.close() - server.close(done); - }); - -}); diff --git a/test/runtime_errors.js b/test/runtime_errors.js deleted file mode 100644 index 6834edc079..0000000000 --- a/test/runtime_errors.js +++ /dev/null @@ -1,234 +0,0 @@ -var Web3 = require('web3'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var fs = require("fs"); -var path = require("path"); -var solc = require("solc"); -var to = require("../lib/utils/to"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - - -function runTests(web3, provider, extraTests) { - var testState = { - accounts: null, - ErrorContract: null, - errorInstance: null, - code: null - } - - before("get accounts", function() { - return web3.eth.getAccounts().then(function(accs) { - testState.accounts = accs; - }); - }); - - before("compile source", function(done) { - this.timeout(10000); - - var source = fs.readFileSync(path.join(__dirname, "RuntimeError.sol"), "utf8"); - var result = solc.compile({sources: {"RuntimeError.sol": source}}, 1); - - testState.code = "0x" + result.contracts["RuntimeError.sol:RuntimeError"].bytecode; - var abi = JSON.parse(result.contracts["RuntimeError.sol:RuntimeError"].interface); - - testState.ErrorContract = new web3.eth.Contract(abi); - testState.ErrorContract._code = testState.code; - testState.ErrorContract.deploy({data: testState.code}) - .send({from: testState.accounts[0], gas: 3141592}) - .then(function(instance) { - // TODO: ugly workaround - not sure why this is necessary. - if (!instance._requestManager.provider) { - instance._requestManager.setProvider(web3.eth._provider); - } - testState.errorInstance = instance; - done(); - }); - }); - - it("should output the transaction hash even if an runtime error occurs (out of gas)", function(done) { - // we can't use `web3.eth.sendTransaction` because it will obfuscate the result - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "eth_sendTransaction", - params: [{ - from: testState.accounts[0], - data: testState.code - }], - id: 1 - }, function(err, result) { - if (provider.options.vmErrorsOnRPCResponse) { - // null & undefined are equivalent for equality tests, but I'm being - // pedantic here for readability's sake - assert(result.error !== null) - assert(result.error !== undefined) - } else { - assert(result.error === undefined) - } - - // null & undefined are equivalent for equality tests, but I'm being - // pedantic here for readability's sake - assert(result.result !== null); - assert(result.result !== undefined); - - assert.equal(result.result.length, 66); // transaction hash - done(); - }); - }); - - it("should output the transaction hash even if a runtime error occurs (revert)", function(done) { - // we can't use `web3.eth.sendTransaction` because it will obfuscate the result - provider.send({ - jsonrpc: '2.0', - id: new Date().getTime(), - method: 'eth_sendTransaction', - params: [{ - from: testState.accounts[0], - to: testState.errorInstance.options.address, - // calls error() - data: '0xc79f8b62', - gas: to.hex(3141592) - }] - }, function(err, response) { - if (provider.options.vmErrorsOnRPCResponse) { - // null & undefined are equivalent for equality tests, but I'm being - // pedantic here for readability's sake - assert(response.error !== null) - assert(response.error !== undefined) - - assert(/revert/.test(response.error.message), `Expected error message (${response.error.message}) to contain 'revert'`); - - } else { - assert(response.error === undefined) - } - - // null & undefined are equivalent for equality tests, but I'm being - // pedantic here for readability's sake - assert(response.result !== null); - assert(response.result !== undefined); - - assert.equal(response.result.length, 66); // transaction hash - - done(); - }); - }); - - it("should have correct return value when calling a method that reverts without message", function(done) { - provider.send({ - jsonrpc: '2.0', - id: new Date().getTime(), - method: 'eth_call', - params: [{ - from: testState.accounts[0], - to: testState.errorInstance.options.address, - // calls error() - data: '0xc79f8b62', - gas: to.hex(3141592) - }] - }, function(err, response) { - if (provider.options.vmErrorsOnRPCResponse) { - // null & undefined are equivalent for equality tests, but I'm being - // pedantic here for readability's sake - assert(response.error !== null) - assert(response.error !== undefined) - assert(response.result === undefined || response.result === null) - - assert(/revert/.test(response.error.message), `Expected error message (${response.error.message}) to contain 'revert'`); - - } else { - assert(response.error === undefined) - assert(response.result === "0x") - } - - done(); - }); - }); - - it("should have correct return value when calling a method that reverts with message", function(done) { - provider.send({ - jsonrpc: '2.0', - id: new Date().getTime(), - method: 'eth_call', - params: [{ - from: testState.accounts[0], - to: testState.errorInstance.options.address, - // calls error() - data: '0xcd4aed30', - gas: to.hex(3141592) - }] - }, function(err, response) { - if (provider.options.vmErrorsOnRPCResponse) { - // null & undefined are equivalent for equality tests, but I'm being - // pedantic here for readability's sake - assert(response.error !== null) - assert(response.error !== undefined) - assert(response.result === undefined || response.result === null) - - // RuntimeError.sol reverts with revert("Message") - assert(/Message/.test(response.error.message), `Expected error message (${response.error.message}) to contain revert reason "Message"`); - assert(/revert/.test(response.error.message), `Expected error message (${response.error.message}) to contain 'revert'`); - - } else { - assert(response.error === undefined) - assert(response.result === "0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000074d65737361676500000000000000000000000000000000000000000000000000") - } - - done(); - }); - }); - - if (extraTests) { - extraTests(testState) - } - - after('shutdown', function(done) { - let provider = web3._provider; - web3.setProvider(); - provider.close(done); - }); -} - -describe("Runtime Errors with vmErrorsOnRPCResponse = true:", function() { - var provider = Ganache.provider({ - vmErrorsOnRPCResponse: true - }); - - var web3 = new Web3(provider); - - runTests(web3, provider, function(testState) { - it("should output instruction index on runtime errors", function(done) { - provider.send({ - jsonrpc: '2.0', - id: new Date().getTime(), - method: 'eth_sendTransaction', - params: [{ - from: testState.accounts[0], - to: testState.errorInstance.options.address, - // calls error() - data: '0xc79f8b62', - gas: to.hex(3141592) - }] - }, function(err, response) { - - let txHash = response.result - - assert(response.error); - assert(response.error.data[txHash]); - assert.equal(response.error.data[txHash].program_counter, 91); // magic number, will change if compiler changes. - done(); - }); - }); - }); - -}) - -describe("Runtime Errors with vmErrorsOnRPCResponse = false:", function() { - var provider = Ganache.provider({ - vmErrorsOnRPCResponse: false - }); - - var web3 = new Web3(provider); - runTests(web3, provider) -}) diff --git a/test/server.js b/test/server.js deleted file mode 100644 index 64355ed2bd..0000000000 --- a/test/server.js +++ /dev/null @@ -1,17 +0,0 @@ -const assert = require("assert"); -const pify = require("pify"); - -const Ganache = require("../index.js"); -const StateManager = require("../lib/statemanager.js"); - -describe('server', () => { - it ('should return instance of StateManager on start', async () => { - const server = Ganache.server(); - try { - const stateManager = await pify(server.listen)(8945); - assert(stateManager instanceof StateManager, 'server.listen must return instance of StateManager'); - } finally { - await pify(server.close)(); - } - }); -}); diff --git a/test/snapshotting.js b/test/snapshotting.js deleted file mode 100644 index 035a2e2f80..0000000000 --- a/test/snapshotting.js +++ /dev/null @@ -1,110 +0,0 @@ -var BN = require("bn.js"); -var Ganache = require("../"); -var async = require("async"); -var Web3 = require("web3"); -var assert = require("assert"); - -describe("Checkpointing / Reverting", function() { - var provider; - var accounts; - var web3 = new Web3(); - var startingBalance; - var snapshotId; - - before("create provider", function() { - provider = Ganache.provider(); - web3.setProvider(provider); - }); - - before("get accounts", function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - before("send a transaction then make a checkpoint", function(done) { - web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei(new BN(1), "ether"), - gas: 90000 - }, function() { - // Since transactions happen immediately, we can assert the balance. - web3.eth.getBalance(accounts[0], function(err, balance) { - if (err) return done(err); - - balance = parseFloat(web3.utils.fromWei(balance, "ether")) - - // Assert the starting balance is where we think it is, including tx costs. - assert(balance > 98.9 && balance < 99); - - startingBalance = balance; - - // Now checkpoint. - provider.send({ - jsonrpc: "2.0", - method: "evm_snapshot", - params: [], - id: new Date().getTime() - }, function(err, result) { - if (err) return done(err); - snapshotId = result.result; - done(); - }); - }) - }); - }); - - it("rolls back successfully", function(done) { - // Send another transaction, check the balance, then roll it back to the old one and check the balance again. - web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei(new BN(1), "ether"), - gas: 90000 - }, function(err, tx_hash) { - if (err) return done(err); - - // Since transactions happen immediately, we can assert the balance. - web3.eth.getBalance(accounts[0], function(err, balance) { - if (err) return done(err); - - balance = parseFloat(web3.utils.fromWei(balance, "ether")) - - // Assert the starting balance is where we think it is, including tx costs. - assert(balance > 97.9 && balance < 98); - - // Now revert. - provider.send({ - jsonrpc: "2.0", - method: "evm_revert", - params: [snapshotId], - id: new Date().getTime() - }, function(err, result) { - if (err) return done(err); - assert(result, "Snapshot should have returned true"); - - // Now check the balance one more time. - web3.eth.getBalance(accounts[0], function(err, balance) { - if (err) return done(err); - - balance = parseFloat(web3.utils.fromWei(balance, "ether")) - - assert(balance == startingBalance, "Should have reverted back to the starting balance"); - - // Now check that the receipt is gone. - web3.eth.getTransactionReceipt(tx_hash, function(err, receipt) { - if (err) return done(err); - - assert.equal(receipt, null, "Receipt should be null as it should have been removed"); - - done(); - }); - }); - }); - }) - }); - }) -}); diff --git a/test/stability.js b/test/stability.js deleted file mode 100644 index b9cafc3be8..0000000000 --- a/test/stability.js +++ /dev/null @@ -1,189 +0,0 @@ -var BN = require('bn.js'); -var Web3 = require('web3'); -var assert = require('assert-match'); -var matchers = require('assert-match/matchers'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var utils = require('ethereumjs-util'); -var pify = require('pify'); - -var regex = matchers.regex - -var logger = { - log: function(message) { - //console.log(message); - } -}; - -describe("stability", function(done) { - var web3 = new Web3(); - var provider; - var port = 12345; - var server; - var accounts; - - before("Initialize the provider", function() { - provider = Ganache.provider({ - }); - web3.setProvider(provider); - }); - - before(function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - - accounts = accs; - done(); - }); - }); - - it("should be able to handle multiple transactions at once and manage nonces accordingly", function(done) { - var expected = 5; - var received = 0; - - var txHandler = function(err, result) { - received += 1; - - if (received > expected) { - throw new Error('Callback called too many times'); - } - - if (err || received == expected) { - return done(err); - } - }; - - // Fire off transaction at once - for (var i = 0; i < expected; i++) { - web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei(new BN(1), "ether") - }, txHandler); - } - }); - - it("should be able to handle batch transactions", function(done) { - var expected = 5; - var received = 0; - - var request = [] - - for (var i = 0; i < expected; i++) { - let req = web3.eth.sendTransaction.request({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei(new BN(1), "ether") - }) - - req.jsonrpc = '2.0' - req.id = 100 + i - - request.push(req) - } - - provider.sendAsync(request, function(err, result) { - assert.deepEqual(err, undefined) - assert(Array.isArray(result)) - assert.deepEqual(result.length, expected) - done(); - }) - - }); - - it("should not crash when receiving transactions which don't pass FakeTransaction validation", function(done) { - provider.send({ - jsonrpc: 2.0, - id: 123, - method: 'eth_sendTransaction', - params:[{ - from: accounts[0], - to: '0x123', //bad address - value: '1000000000000000000' // 1 ETH - }] - }, function(err, result) { - assert.notEqual(err, undefined) - assert.notEqual(result.error, undefined) - done() - }) - }) - - it('should not crash when receiving a request with too many arguments', function() { - // At time of writing, `evm_mine` takes 0 arguments - return pify(provider.send)({ - jsonrpc: 2.0, - id: 123, - method: 'evm_mine', - params:[ - '0x1', - '0x2', - '0x3', - '0x4', - '0x5', - '0x6', - '0x7', - '0x8', - '0x9', - '0xA' - // 10 oughtta do it! - ] - }).catch(err => { - assert.deepEqual(err.message, regex(/Incorrect number of arguments\. Method \'evm_mine\' requires between \d+ and \d+ arguments\. Request specified \d+ arguments: \[[^\]]*\]\./)); - });// nothing to check from here, if the promise rejects, test fails - }) - - //TODO: remove `.skip` when working on and/or submitting fix for issue #453 - describe.skip("race conditions", function(done) { - var web3 = new Web3(); - var provider; - var accounts; - - before("initialize the provider", function() { - provider = Ganache.provider({ - }); - web3.setProvider(provider); - }); - - before("get accounts", function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - - accounts = accs; - done(); - }); - }); - - it("should not cause 'get' of undefined", function(done) { - process.prependOnceListener('uncaughtException', function(err) { - done(err); - }); - - var blockchain = provider.manager.state.blockchain; - blockchain.vm.stateManager.checkpoint(); // processCall or processBlock - blockchain.stateTrie.get(utils.toBuffer(accounts[0]), function() {}); // getCode (or any function that calls trie.get) - blockchain.vm.stateManager.revert(function() { - done(); - }); // processCall or processBlock - }); - - it("should not cause 'pop' of undefined", function(done) { - process.prependOnceListener('uncaughtException', function(err) { - done(err); - }); - - var blockchain = provider.manager.state.blockchain; - blockchain.vm.stateManager.checkpoint(); // processCall #1 - // processNextBlock triggered by interval mining which at some point calls vm.stateManager.commit() and blockchain.putBlock() - blockchain.processNextBlock(function(err, tx, results) { - blockchain.vm.stateManager.revert(function() { // processCall #1 finishes - blockchain.latestBlock(function (err, latestBlock) { - blockchain.stateTrie.root = latestBlock.header.stateRoot; // getCode #1 (or any function with this logic) - web3.eth.call({}, function() { - done(); - }); // processCall #2 - }); - }); - }); - }); - }); -}); - diff --git a/test/swarm.js b/test/swarm.js deleted file mode 100644 index e6e34120ed..0000000000 --- a/test/swarm.js +++ /dev/null @@ -1,27 +0,0 @@ -var Web3 = require('web3'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); - -describe("Swarm", function(done) { - var web3 = new Web3(); - var provider; - - before("Initialize the provider", function() { - provider = Ganache.provider(); - web3.setProvider(provider); - }); - - it.skip("should get swarm info (bzz_info)", function(done) { - web3.bzz.getInfo(function(err, result){ - assert.isArray(result, "Stub returns empty array") - done(); - }) - }); - - it.skip("should get swarm hive (bzz_hive)", function(done) { - web3.bzz.getHive(function(err, result){ - assert.isArray(result, "Stub returns empty array") - done(); - }) - }); -}); diff --git a/test/time_adjust.js b/test/time_adjust.js deleted file mode 100644 index ad633235bf..0000000000 --- a/test/time_adjust.js +++ /dev/null @@ -1,142 +0,0 @@ -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require('assert-match'); -var matchers = require('assert-match/matchers'); -var gte = matchers.gte -var lte = matchers.lte -var Web3 = require("web3"); - -describe('Time adjustment', function() { - var startTime = new Date("Wed Aug 24 2016 00:00:00 GMT-0700 (PDT)"); - var provider = Ganache.provider({ - time: startTime - }); - var web3 = new Web3(provider); - var secondsToJump = 5 * 60 * 60; - - var timestampBeforeJump; - - function send(method, params, callback) { - if (typeof params == "function") { - callback = params; - params = []; - } - - provider.send({ - jsonrpc: "2.0", - method: method, - params: params || [], - id: new Date().getTime() - }, callback); - }; - - before('get current time', function(done) { - web3.eth.getBlock('latest', function(err, block){ - if(err) return done(err) - timestampBeforeJump = block.timestamp - done() - }) - }) - - it('should mine the first block at the time provided', function(done) { - web3.eth.getBlock(0, function(err, result) { - // give ourselves a 25ms window for this to succeed - let acceptableStartTime = startTime / 1000 | 0; - let acceptableEndTime = acceptableStartTime + 25; - assert.deepEqual(result.timestamp, gte(acceptableStartTime)); - assert.deepEqual(result.timestamp, lte(acceptableEndTime)); - done(); - }); - }); - - it('should jump 5 hours', function(done) { - this.timeout(5000) // this is timing out on travis for some reason :-( - // Adjust time - send("evm_increaseTime", [secondsToJump], function(err, result) { - if (err) return done(err); - - // Mine a block so new time is recorded. - send("evm_mine", function(err, result) { - if (err) return done(err); - - web3.eth.getBlock('latest', function(err, block){ - if(err) return done(err) - var secondsJumped = block.timestamp - timestampBeforeJump - - // Somehow it jumps an extra 18 seconds, ish, when run inside the whole - // test suite. It might have something to do with when the before block - // runs and when the test runs. Likely the last block didn't occur for - // awhile. - assert(secondsJumped >= secondsToJump) - done() - }) - }) - }) - }) - - it('should mine a block at the given timestamp', function(done) { - // Adjust time - var expectedMinedTimestamp = 1000000; - send("evm_mine", [expectedMinedTimestamp], function(err, result) { - if (err) return done(err); - - web3.eth.getBlock('latest', function(err, block) { - if(err) return done(err); - assert(block.timestamp == expectedMinedTimestamp); - done(); - }); - }); - }); - - it('should revert time adjustments when snapshot is reverted', function(done) { - // Adjust time - web3.eth.getBlock('latest', function(err, block) { - if(err) return done(err); - var previousBlockTime = block.timestamp; - var originalTimeAdjustment = provider.manager.state.blockchain.timeAdjustment; - - send("evm_snapshot", function(err, result) { - // jump forward another 5 hours - send("evm_increaseTime", [secondsToJump], function(err, result) { - if (err) return done(err); - - var currentTimeAdjustment = provider.manager.state.blockchain.timeAdjustment; - assert.equal(currentTimeAdjustment, originalTimeAdjustment + secondsToJump); - - // Mine a block so new time is recorded. - send("evm_mine", function(err, result) { - if (err) return done(err); - - send("evm_revert", [1], function(err, result) { - var revertedTimeAdjustment = provider.manager.state.blockchain.timeAdjustment; - assert.equal(revertedTimeAdjustment, originalTimeAdjustment); - done() - }) - }) - }) - }) - }) - }) - - it('should allow setting of time', function(done) { - web3.eth.getBlock('latest', function(err, block) { - if (err) return done(err) - - var previousTime = block.timestamp - - send("evm_setTime", [new Date(previousTime - secondsToJump)], function(err, result) { - if (err) return done(err); - - // Mine a block so new time is recorded. - send("evm_mine", function(err, result) { - if (err) return done(err); - - web3.eth.getBlock('latest', function(err, block){ - if(err) return done(err) - assert(previousTime > block.timestamp); - done() - }) - }) - }) - }) - }); -}) diff --git a/test/transaction_ordering.js b/test/transaction_ordering.js deleted file mode 100644 index 4d6ab76187..0000000000 --- a/test/transaction_ordering.js +++ /dev/null @@ -1,90 +0,0 @@ -var Web3 = require('web3'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var assert = require('assert'); -var to = require('../lib/utils/to.js'); - -describe("Transaction Ordering", function() { - var accounts; - var web3 = new Web3(Ganache.provider()); - - before(function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - - accounts = accs; - done(); - }); - }); - - beforeEach(function(done){ - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "miner_stop", - }, done) - }); - - afterEach(function(done){ - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "miner_start", - params: [1] - }, done) - }); - - it("should order queued transactions correctly by nonce before adding to the block", function(done) { - var tx_data = {} - tx_data.to = accounts[1]; - tx_data.from = accounts[0]; - tx_data.value = 0x1; - tx_data.nonce = 0; - tx_data.gas = 21000; - web3.eth.sendTransaction(tx_data, function(err, tx) { - if (err){return done(err)} - tx_data.nonce=1; - web3.eth.sendTransaction(tx_data, function(err, tx){ - if (err){return done(err)} - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "miner_start", - params: [1] - }, function(err,tx){ - web3.eth.getBlock("latest", function(err, block) { - if (err) return done(err); - assert.equal(block.transactions.length, 2, "Latest block should have two transactions"); - done(); - }); - }) - }) - }) - }); - - it("should order queued transactions correctly by price before adding to the block", function(done) { - var tx_data = {} - tx_data.to = accounts[1]; - tx_data.from = accounts[0]; - tx_data.value = 0x1; - tx_data.gas = 21000; - tx_data.gasPrice = 0x1 - web3.eth.sendTransaction(tx_data, function(err, tx) { - if (err){return done(err)} - tx_data.gasPrice=2; - tx_data.from = accounts[1]; - web3.eth.sendTransaction(tx_data, function(err, tx){ - if (err){return done(err)} - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "miner_start", - params: [1] - }, function(err,tx){ - web3.eth.getBlock("latest", true, function(err, block) { - if (err) return done(err); - assert.equal(block.transactions.length, 2, "Latest block should have two transactions"); - assert.equal(to.number(block.transactions[0].gasPrice), 2) - assert.equal(to.number(block.transactions[1].gasPrice), 1) - done(); - }); - }) - }) - }) - }); -}); diff --git a/test/transaction_rejection.js b/test/transaction_rejection.js deleted file mode 100644 index fa92cda208..0000000000 --- a/test/transaction_rejection.js +++ /dev/null @@ -1,149 +0,0 @@ -var Web3 = require('web3'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var fs = require("fs"); -var path = require("path"); -var solc = require("solc"); -var to = require("../lib/utils/to") - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -describe("Transaction rejection", function() { - var provider = Ganache.provider({ - // important: we want to make sure we get tx rejections as rpc errors even - // if we don't want runtime errors as RPC erros - vmErrorsOnRPCResponse: false - }) - - var web3 = new Web3(provider); - - var accounts; - var estimateGasContractData; - var estimateGasContractAbi; - var EstimateGasContract; - var EstimateGasContractAddress; - var estimateGasInstance; - var deploymentReceipt; - var estimateGasContractAddress; - var source = fs.readFileSync(path.join(__dirname, "EstimateGas.sol"), "utf8"); - - before("get accounts", function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - before("lock account 1", function() { - return web3.eth.personal.lockAccount(accounts[1]) - }) - - before("compile source", function() { - this.timeout(10000); - var result = solc.compile({sources: {"EstimateGas.sol": source}}, 1); - - estimateGasContractData = "0x" + result.contracts["EstimateGas.sol:EstimateGas"].bytecode; - estimateGasContractAbi = JSON.parse(result.contracts["EstimateGas.sol:EstimateGas"].interface); - - EstimateGasContract = new web3.eth.Contract(estimateGasContractAbi); - return EstimateGasContract.deploy({data: estimateGasContractData}) - .send({from: accounts[0], gas: 3141592}) - .on('receipt', function (receipt) { - deploymentReceipt = receipt; - }) - .then(function(instance) { - // TODO: ugly workaround - not sure why this is necessary. - if (!instance._requestManager.provider) { - instance._requestManager.setProvider(web3.eth._provider); - } - estimateGasInstance = instance; - estimateGasContractAddress = to.hex(instance.options.address); - }); - }); - - it("should reject transaction if nonce is incorrect", function(done) { - testTransactionForRejection({ - nonce: 0xffff - }, /the tx doesn't have the correct nonce/, done) - }); - - it("should reject transaction if from account is missing", function(done) { - testTransactionForRejection({ - from: undefined - }, /from not found; is required/, done) - }); - - it("should reject transaction if from account is invalid/unknown", function(done) { - testTransactionForRejection({ - from: '0x0000000000000000000000000000000000000001' - }, /sender account not recognized/, done) - }); - - it("should reject transaction if from known account which is locked", function(done) { - testTransactionForRejection({ - from: accounts[1], - }, /signer account is locked/, done) - }); - - it("should reject transaction if gas limit exceeds block gas limit", function(done) { - testTransactionForRejection({ - gas: 0xFFFFFFFF, - }, /Exceeds block gas limit/, done) - }); - - it("should reject transaction if insufficient funds", function(done) { - testTransactionForRejection({ - value: web3.utils.toWei('100000', 'ether') - }, /sender doesn't have enough funds to send tx/, done) - }); - - function testTransactionForRejection(paramsOverride, messageRegex, done) { - let params = Object.assign({ - from: accounts[0], - to: estimateGasContractAddress, - gas: to.hex(3141592), - data: '0x91ea8a0554696d000000000000000000000000000000000000000000000000000000000041206772656174206775790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005' - }, paramsOverride) - - let request = { - jsonrpc: 2.0, - id: new Date().getTime(), - method: 'eth_sendTransaction', - params: [ params ] - } - - // don't send with web3 because it'll inject its own checks - provider.send(request, (err, response) => { - // cyclomatic complexity? what's that? :-( - if (response.error) { - if (response.error.message) { - if (messageRegex.test(response.error.message)) { - // success! - return done() - } else { - // wrong error message - return done(new Error(`Expected error message matching ${messageRegex}, got ${response.error.message}`)) - } - } else { - return done(new Error(`Error was returned which had no message`)) - } - } else if (response.result) { - web3.eth.getTransactionReceipt(response.result) - .then((result) => { - if (to.number(result.status) == 0) { - return done(new Error('TX rejections should return error, but returned receipt with zero status instead')) - } else { - return done(new Error(`TX should have rejected prior to running. Instead transaction ran successfully (receipt.status == ${to.number(result.status)})`)) - } - }).catch(error => { - return done(error) - }) - } else { - return done(new Error('eth_sendTransaction responded with empty RPC response')) - } - }) - } -}) diff --git a/test/unlimited_contract_size.js b/test/unlimited_contract_size.js deleted file mode 100644 index c5e870dc42..0000000000 --- a/test/unlimited_contract_size.js +++ /dev/null @@ -1,88 +0,0 @@ -var Web3 = require('web3'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var fs = require("fs"); -var path = require("path"); -var solc = require("solc"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -let mnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat' - -describe("Unlimited Contract Size", function() { - let contract; - - before("compile contract", function() { - var result = solc.compile({sources: {"LargeContract.sol": fs.readFileSync(path.join(__dirname, "LargeContract.sol"), "utf8")}}, 1); - contract = { - bytecode: "0x" + result.contracts["LargeContract.sol:LargeContract"].bytecode, - abi: JSON.parse(result.contracts["LargeContract.sol:LargeContract"].interface) - } - }); - - describe("Disallow Unlimited Contract Size", function() { - var provider = new Ganache.provider({ - mnemonic, - allowUnlimitedContractSize: false, - gasLimit: 20000000 - }); - var web3 = new Web3(provider); - var accounts; - - before("get accounts", function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - it("should fail deployment", function(done) { - let DummyContract = new web3.eth.Contract(contract.abi); - DummyContract.deploy({ - data: contract.bytecode - }) - .send({from: accounts[0], gas: 20000000}) - .then(function(instance) { - done(new Error("succeeded deployment when it should have failed")); - }) - .catch(function(error) { - done(); - }); - }); - }); - - describe("Allow Unlimited Contract Size", function() { - var provider = new Ganache.provider({ - mnemonic, - allowUnlimitedContractSize: true, - gasLimit: 20000000 - }); - var web3 = new Web3(provider); - var accounts; - - before("get accounts", function(done) { - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - accounts = accs; - done(); - }); - }); - - it("should succeed deployment", function(done) { - let DummyContract = new web3.eth.Contract(contract.abi); - DummyContract.deploy({ - data: contract.bytecode - }) - .send({from: accounts[0], gas: 20000000}) - .then(function(instance) { - done() - }) - .catch(function(error) { - console.log(error); - done(new Error("failed deployment when it should have succeeded")); - }); - }); - }); -}); \ No newline at end of file diff --git a/test/vm.js b/test/vm.js deleted file mode 100644 index 6a5c55d5cd..0000000000 --- a/test/vm.js +++ /dev/null @@ -1,75 +0,0 @@ -var Web3 = require('web3'); -var Transaction = require('ethereumjs-tx'); -var utils = require('ethereumjs-util'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); -var solc = require("solc"); -var fs = require("fs"); -var to = require("../lib/utils/to"); - -// Thanks solc. At least this works! -// This removes solc's overzealous uncaughtException event handler. -process.removeAllListeners("uncaughtException"); - -var logger = { - log: function(message) { - //console.log(message); - } -}; - -var web3 = new Web3(); -web3.setProvider(Ganache.provider({ - /*blockTime: 100,*/ - logger: logger, - seed: "1337" -})); - -describe("revert opcode", function() { - var testContext = {}; - - before(function (done) { - this.timeout(10000); - testContext.source = fs.readFileSync("./test/Revert.sol", {encoding: "utf8"}); - testContext.solcResult = solc.compile(testContext.source, false); - - testContext.revertContract = { - solidity: testContext.source, - abi: testContext.solcResult.contracts[":Revert"].interface, - binary: "0x" + testContext.solcResult.contracts[":Revert"].bytecode, - runtimeBinary: '0x' + testContext.solcResult.contracts[":Revert"].runtimeBytecode - }; - - web3.eth.getAccounts(function(err, accs) { - if (err) return done(err); - - testContext.accounts = accs; - - return done(); - }); - }); - - it("should return a transaction receipt with status 0 on REVERT", function() { - var revertCode = testContext.revertContract.binary; - var revertAbi = JSON.parse(testContext.revertContract.abi); - - var RevertContract = new web3.eth.Contract(revertAbi); - RevertContract._code = revertCode; - return RevertContract.deploy({ data: revertCode }) - .send({from: testContext.accounts[0], gas: 3141592 }) - .then(function (instance) { - // TODO: ugly workaround - not sure why this is necessary. - if (!instance._requestManager.provider) { - instance._requestManager.setProvider(web3.eth._provider); - } - return instance.methods.alwaysReverts(5).send({ from: testContext.accounts[0] }) - }) - .catch(function(err){ - assert.equal(err.results[err.hashes[0]].error, "revert", "Expected error result not returned."); - return web3.eth.getTransactionReceipt(err.hashes[0]) - }) - .then(function(receipt) { - assert.notEqual(receipt, null, "Transaction receipt shouldn't be null"); - assert.equal(receipt.status, 0, "Reverted (failed) transactions should have a status of 0."); - }); - }); -}); diff --git a/test/whisper.js b/test/whisper.js deleted file mode 100644 index 9046cc5744..0000000000 --- a/test/whisper.js +++ /dev/null @@ -1,19 +0,0 @@ -var Web3 = require('web3'); -var assert = require('assert'); -var Ganache = require(process.env.TEST_BUILD ? "../build/ganache.core." + process.env.TEST_BUILD + ".js" : "../index.js"); - -describe("Whisper", function(done) { - var web3 = new Web3(); - var provider; - - before("Initialize the provider", function() { - provider = Ganache.provider(); - web3.setProvider(provider); - }); - - it("should call get whisper version (shh_version)", function() { - return web3.shh.getVersion(function(err, result){ - assert.equal(result, "2", "Whisper version should be 2"); - }) - }); -}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..9bba1c6888 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "outDir": "lib", + "alwaysStrict": true, + "declaration": true, + "skipLibCheck": true, + "module": "CommonJS", + "esModuleInterop": true, + "target": "ES2020", + "moduleResolution": "node", + "noErrorTruncation": true, + "sourceMap": true, + "strict": true, + /** `noImplicitAny: false` and `strictNullChecks: false` are temporary during initial rapid development. */ + "strictNullChecks": false, + "noImplicitAny": false, + "newLine": "lf", + "lib": ["ES2020"], + "typeRoots": ["./node_modules/@types", "src/@types"], + "experimentalDecorators": true, + "paths": { + "@ganache/cli/cli": ["../cli/lib/cli"] + }, + "plugins": [ + { + "transform": "ts-transformer-inline-file/transformer" + }, + { + "transform": "@zerollup/ts-transform-paths", + "exclude": "*" + } + ] + } +} diff --git a/webpack/base.webpack.config.js b/webpack/base.webpack.config.js deleted file mode 100644 index e9af1c8d34..0000000000 --- a/webpack/base.webpack.config.js +++ /dev/null @@ -1,49 +0,0 @@ -const { merge } = require("lodash"); -const { resolve } = require("path"); -const { IgnorePlugin } = require("webpack"); - -const outputDir = resolve(__dirname, "..", "build"); - -module.exports = (override) => { - return merge({}, { - output: { - path: outputDir - }, - devtool: "source-map", - externals: [ - (context, request, callback) => { - // webpack these modules: - // we actually only care about scrypt and eth-block-tracker here, as those are the only native modules - // but webpack won't detect them if we don't traverse the dependency tree to get to them - if (/^(ethereumjs-wallet|scrypt|web3|eth-block-tracker)(\/.*)?$/.test(request)) { - return callback(); - } - - // we want to webpack all local files (files starting with a .) - if(/^\./.test(request)){ - return callback(); - } - - // we don't want to webpack any other modules - return callback(null, 'commonjs ' + request); - } - ], - resolve: { - alias: { - // eth-block-tracker is es6 but automatically builds an es5 version for us on install. thanks eth-block-tracker! - "eth-block-tracker": "eth-block-tracker/dist/es5/index.js", - - // replace native `scrypt` module with pure js `js-scrypt` - "scrypt": "js-scrypt", - - // replace native `secp256k1` with pure js `elliptic.js` - "secp256k1": "secp256k1/elliptic.js" - } - }, - plugins: [ - // ignore these plugins completely - new IgnorePlugin(/^(?:electron|ws)$/) - ], - mode: "production" - }, override); -}; \ No newline at end of file diff --git a/webpack/node/core.webpack.config.js b/webpack/node/core.webpack.config.js deleted file mode 100644 index 4ef34c77eb..0000000000 --- a/webpack/node/core.webpack.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { join } = require("path"); -const applyBaseConfig = require("../base.webpack.config"); - -const outputDir = join(__dirname, "..", "..", "build"); -const outputFilename = "ganache.core.node.js"; - -module.exports = applyBaseConfig({ - entry: "./public-exports.js", - target: "node", - output: { - path: outputDir, - filename: outputFilename, - library: "Ganache", - libraryTarget: "umd", - umdNamedDefine: true - } -}); \ No newline at end of file diff --git a/webpack/node/provider.webpack.config.js b/webpack/node/provider.webpack.config.js deleted file mode 100644 index 9c477d6696..0000000000 --- a/webpack/node/provider.webpack.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { join } = require("path"); -const applyBaseConfig = require("../base.webpack.config"); - -const outputDir = join(__dirname, "..", "..", "build"); -const outputFilename = "ganache.provider.node.js"; - -module.exports = applyBaseConfig({ - entry: "./lib/provider.js", - target: "node", - output: { - path: outputDir, - filename: outputFilename, - library: "GanacheProvider", - libraryTarget: "umd", - umdNamedDefine: true - } -}); \ No newline at end of file diff --git a/webpack/node/server.webpack.config.js b/webpack/node/server.webpack.config.js deleted file mode 100644 index ddadd9d455..0000000000 --- a/webpack/node/server.webpack.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { join } = require("path"); -const applyBaseConfig = require("../base.webpack.config"); - -const outputDir = join(__dirname, "..", "..", "build"); -const outputFilename = "ganache.server.node.js"; - -module.exports = applyBaseConfig({ - entry: "./lib/server.js", - target: "node", - output: { - path: outputDir, - filename: outputFilename, - library: "GanacheServer", - libraryTarget: "umd", - umdNamedDefine: true - } -}); \ No newline at end of file diff --git a/webpack/web-experimental/core.webpack.config.js b/webpack/web-experimental/core.webpack.config.js deleted file mode 100644 index 5f0bbc368c..0000000000 --- a/webpack/web-experimental/core.webpack.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { join } = require("path"); -const applyBaseConfig = require("./webbase.webpack.config"); - -const outputDir = join(__dirname, "..", "..", "build"); -const outputFilename = "ganache.core.web-experimental.js"; - -module.exports = applyBaseConfig({ - entry: ["core-js/fn/promise", "./index.js"], - target: "web", - output: { - path: outputDir, - filename: outputFilename, - library: "Ganache", - libraryTarget: "umd", - umdNamedDefine: true - } -}); \ No newline at end of file diff --git a/webpack/web-experimental/provider.webpack.config.js b/webpack/web-experimental/provider.webpack.config.js deleted file mode 100644 index 84f13cfa6e..0000000000 --- a/webpack/web-experimental/provider.webpack.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { join } = require("path"); -const applyBaseConfig = require("./webbase.webpack.config"); - -const outputDir = join(__dirname, "..", "..", "build"); -const outputFilename = "ganache.provider.web-experimental.js"; - -module.exports = applyBaseConfig({ - entry: "./lib/provider.js", - target: "web", - output: { - path: outputDir, - filename: outputFilename, - library: "GanacheProvider", - libraryTarget: "umd", - umdNamedDefine: true - } -}); \ No newline at end of file diff --git a/webpack/web-experimental/server.webpack.config.js b/webpack/web-experimental/server.webpack.config.js deleted file mode 100644 index 1886420ae1..0000000000 --- a/webpack/web-experimental/server.webpack.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { join } = require("path"); -const applyBaseConfig = require("./webbase.webpack.config"); - -const outputDir = join(__dirname, "..", "..", "build"); -const outputFilename = "ganache.server.web-experimental.js"; - -module.exports = applyBaseConfig({ - entry: "./lib/server.js", - target: "web", - output: { - path: outputDir, - filename: outputFilename, - library: "GanacheServer", - libraryTarget: "umd", - umdNamedDefine: true - } -}); \ No newline at end of file diff --git a/webpack/web-experimental/webbase.webpack.config.js b/webpack/web-experimental/webbase.webpack.config.js deleted file mode 100644 index 3a304f36c2..0000000000 --- a/webpack/web-experimental/webbase.webpack.config.js +++ /dev/null @@ -1,12 +0,0 @@ -const { merge } = require("lodash"); -const applyBaseConfig = require("../base.webpack.config"); - -module.exports = (override) => { - return merge({}, applyBaseConfig({ - resolve: { - alias: { - 'fs': 'browserfs/dist/shims/fs.js' - } - } - }), override); -}; \ No newline at end of file