diff --git a/.circleci/config.yml b/.circleci/config.yml index 52c8f0db..ee72ec4d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -35,6 +35,46 @@ common: &common - ./eggs key: cache-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}-{{ checksum "tox.ini" }} +integration: &integration + working_directory: ~/repo + steps: + - checkout + - run: + name: merge pull request base + command: ./.circleci/merge_pr.sh + - run: + name: merge pull request base (2nd try) + command: ./.circleci/merge_pr.sh + when: on_fail + - run: + name: merge pull request base (3rd try) + command: ./.circleci/merge_pr.sh + when: on_fail + - restore_cache: + keys: + - cache-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}-{{ checksum "tox.ini" }} + - run: + name: install dependencies (python) + command: pip install --user tox + - run: + name: install dependencies (node) + command: sudo -E bash tests/integration/ethers-cli/setup_node_v12.sh && sudo apt-get install -y nodejs + - run: + name: Build ethers-cli + command: cd tests/integration/ethers-cli && sudo npm install -g . && cd ../../../ + - run: + name: run tox + command: ~/.local/bin/tox -r + - save_cache: + paths: + - .hypothesis + - .tox + - ~/.cache/pip + - ~/.local + - ./eggs + - tests/integration/ethers-cli/node_modules + key: cache-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}-{{ checksum "tox.ini" }} + jobs: doctest: <<: *common @@ -66,6 +106,24 @@ jobs: - image: circleci/python:3.8 environment: TOXENV: py38-core + py36-integration: + <<: *integration + docker: + - image: circleci/python:3.6 + environment: + TOXENV: py36-integration + py37-integration: + <<: *integration + docker: + - image: circleci/python:3.7 + environment: + TOXENV: py37-integration + py38-integration: + <<: *integration + docker: + - image: circleci/python:3.8 + environment: + TOXENV: py38-integration workflows: version: 2 test: @@ -75,3 +133,6 @@ workflows: - py36-core - py37-core - py38-core + - py36-integration + - py37-integration + - py38-integration diff --git a/README.md b/README.md index 4797b65c..0e26762a 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,15 @@ virtualenv -p python3 venv pip install -e .[dev] ``` +To run the integration test cases, you need to install node and the custom cli tool as follows: + +```sh +apt-get install -y nodejs # As sudo +./tests/integration/ethers-cli/setup_node_v12.sh # As sudo +cd tests/integration/ethers-cli +npm install -g . # As sudo +``` + ### Testing Setup During development, you might like to have tests run on every file save. diff --git a/eth_account/account.py b/eth_account/account.py index 24eaf0c9..ca3493cd 100644 --- a/eth_account/account.py +++ b/eth_account/account.py @@ -46,6 +46,12 @@ from eth_account.datastructures import ( AttributeDict, ) +from eth_account.hdaccount import ( + ETHEREUM_DEFAULT_PATH, + generate_mnemonic, + key_from_seed, + seed_from_mnemonic, +) from eth_account.messages import ( SignableMessage, _hash_eip191_message, @@ -65,6 +71,16 @@ class Account(object): _default_kdf = os.getenv('ETH_ACCOUNT_KDF', 'scrypt') + # Enable unaudited features (off by default) + _use_unaudited_hdwallet_features = False + + @classmethod + def enable_unaudited_hdwallet_features(cls): + """ + Use this flag to enable unaudited HD Wallet features. + """ + cls._use_unaudited_hdwallet_features = True + @combomethod def create(self, extra_entropy=''): r""" @@ -229,6 +245,93 @@ def from_key(self, private_key): key = self._parsePrivateKey(private_key) return LocalAccount(key, self) + @combomethod + def from_mnemonic(self, + mnemonic: str, + passphrase: str="", + account_path: str=ETHEREUM_DEFAULT_PATH): + """ + + .. CAUTION:: This feature is experimental, unaudited, and likely to change soon + + :param str mnemonic: space-separated list of BIP39 mnemonic seed words + :param str passphrase: Optional passphrase used to encrypt the mnemonic + :param str account_path: Specify an alternate HD path for deriving the seed using + BIP32 HD wallet key derivation. + :return: object with methods for signing and encrypting + :rtype: LocalAccount + + .. code-block:: python + + >>> from eth_account import Account + >>> Account.enable_unaudited_hdwallet_features() + >>> acct = Account.from_mnemonic( + "coral allow abandon recipe top tray caught video climb similar prepare bracket " + "antenna rubber announce gauge volume hub hood burden skill immense add acid") + >>> acct.address + '0x9AdA5dAD14d925f4df1378409731a9B71Bc8569d' + + # These methods are also available: sign_message(), sign_transaction(), encrypt() + # They correspond to the same-named methods in Account.* + # but without the private key argument + """ + if not self._use_unaudited_hdwallet_features: + raise AttributeError( + "The use of the Mnemonic features of Account is disabled by default until " + "its API stabilizes. To use these features, please enable them by running " + "`Account.enable_unaudited_hdwallet_features()` and try again." + ) + seed = seed_from_mnemonic(mnemonic, passphrase) + private_key = key_from_seed(seed, account_path) + key = self._parsePrivateKey(private_key) + return LocalAccount(key, self) + + @combomethod + def create_with_mnemonic(self, + passphrase: str="", + num_words: int=12, + language: str="english", + account_path: str=ETHEREUM_DEFAULT_PATH): + r""" + + .. CAUTION:: This feature is experimental, unaudited, and likely to change soon + + Creates a new private key, and returns it as a :class:`~eth_account.local.LocalAccount`, + alongside the mnemonic that can used to regenerate it using any BIP39-compatible wallet. + + :param str passphrase: Extra passphrase to encrypt the seed phrase + :param int num_words: Number of words to use with seed phrase. Default is 12 words. + Must be one of [12, 15, 18, 21, 24]. + :param str language: Language to use for BIP39 mnemonic seed phrase. + :param str account_path: Specify an alternate HD path for deriving the seed using + BIP32 HD wallet key derivation. + :returns: A tuple consisting of an object with private key and convenience methods, + and the mnemonic seed phrase that can be used to restore the account. + :rtype: (LocalAccount, str) + + .. code-block:: python + + >>> from eth_account import Account + >>> Account.enable_unaudited_hdwallet_features() + >>> acct, mnemonic = Account.create_with_mnemonic() + >>> acct.address + '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' + >>> acct == Account.from_mnemonic(mnemonic) + True + + # These methods are also available: sign_message(), sign_transaction(), encrypt() + # They correspond to the same-named methods in Account.* + # but without the private key argument + """ + if not self._use_unaudited_hdwallet_features: + raise AttributeError( + "The use of the Mnemonic features of Account is disabled by default until " + "its API stabilizes. To use these features, please enable them by running " + "`Account.enable_unaudited_hdwallet_features()` and try again." + ) + mnemonic = generate_mnemonic(num_words, language) + return self.from_mnemonic(mnemonic, passphrase, account_path), mnemonic + @combomethod def recover_message(self, signable_message: SignableMessage, vrs=None, signature=None): r""" diff --git a/eth_account/hdaccount/__init__.py b/eth_account/hdaccount/__init__.py index e69de29b..94af87c3 100644 --- a/eth_account/hdaccount/__init__.py +++ b/eth_account/hdaccount/__init__.py @@ -0,0 +1,30 @@ +from eth_utils import ( + ValidationError, +) + +from .deterministic import ( + HDPath, +) +from .mnemonic import ( + Mnemonic, +) + +ETHEREUM_DEFAULT_PATH = "m/44'/60'/0'/0/0" + + +def generate_mnemonic(num_words: int, lang: str) -> str: + return Mnemonic(lang).generate(num_words) + + +def seed_from_mnemonic(words: str, passphrase: str) -> bytes: + lang = Mnemonic.detect_language(words) + expanded_words = Mnemonic(lang).expand(words) + if not Mnemonic(lang).is_mnemonic_valid(expanded_words): + raise ValidationError( + f"Provided words: '{expanded_words}', are not a valid BIP39 mnemonic phrase!" + ) + return Mnemonic.to_seed(expanded_words, passphrase) + + +def key_from_seed(seed: bytes, account_path: str): + return HDPath(account_path).derive(seed) diff --git a/eth_account/hdaccount/deterministic.py b/eth_account/hdaccount/deterministic.py index 76e94b9b..526514be 100644 --- a/eth_account/hdaccount/deterministic.py +++ b/eth_account/hdaccount/deterministic.py @@ -133,18 +133,18 @@ def derive_child_key( The function CKDpriv((k_par, c_par), i) → (k_i, c_i) computes a child extended private key from the parent extended private key: - - Check whether i ≥ 2**31 (whether the child is a hardened key). - - If so (hardened child): - let I = HMAC-SHA512(Key = c_par, Data = 0x00 || ser_256(k_par) || ser_32(i)). - (Note: The 0x00 pads the private key to make it 33 bytes long.) - - If not (normal child): - let I = HMAC-SHA512(Key = c_par, Data = ser_P(point(k_par)) || ser_32(i)). - - Split I into two 32-byte sequences, I_L and I_R. - - The returned child key k_i is parse_256(I_L) + k_par (mod n). - - The returned chain code c_i is I_R. - - In case parse_256(I_L) ≥ n or k_i = 0, the resulting key is invalid, - and one should proceed with the next value for i. - (Note: this has probability lower than 1 in 2**127.) + 1. Check whether the child is a hardened key (i ≥ 2**31). If the child is a hardened key, + let I = HMAC-SHA512(Key = c_par, Data = 0x00 || ser_256(k_par) || ser_32(i)). + (Note: The 0x00 pads the private key to make it 33 bytes long.) + If it is not a hardened key, then + let I = HMAC-SHA512(Key = c_par, Data = ser_P(point(k_par)) || ser_32(i)). + 2. Split I into two 32-byte sequences, I_L and I_R. + 3. The returned child key k_i is parse_256(I_L) + k_par (mod n). + 4. The returned chain code c_i is I_R. + 5. In case parse_256(I_L) ≥ n or k_i = 0, the resulting key is invalid, + and one should proceed with the next value for i. + (Note: this has probability lower than 1 in 2**127.) + """ assert len(parent_chain_code) == 32 if isinstance(node, HardNode): diff --git a/pytest.ini b/pytest.ini index 98061469..a6d92d0d 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,7 +1,9 @@ [pytest] -addopts= -v --showlocals --doctest-modules --durations 10 +addopts= -v --showlocals --doctest-modules --durations 10 --ignore tests/integration/ethers-cli python_paths= . xfail_strict=true +markers = + compatibility: mark a test to be run during compatibility fuzz testing [pytest-watch] runner= pytest --failed-first --maxfail=1 diff --git a/tests/core/test_hdaccount.py b/tests/core/test_hdaccount.py new file mode 100644 index 00000000..29af6d9d --- /dev/null +++ b/tests/core/test_hdaccount.py @@ -0,0 +1,94 @@ +import pytest + +from eth_utils import ( + ValidationError, +) + +from eth_account import ( + Account, +) +from eth_account.hdaccount import ( + ETHEREUM_DEFAULT_PATH, +) + +Account.enable_unaudited_hdwallet_features() + + +@pytest.mark.parametrize("mnemonic,account_path,expected_address", [ + # Ganache + # https://github.com/trufflesuite/ganache-core/blob/d1cb5318cb3c694743f86f29d74/test/accounts.js + ( + "into trim cross then helmet popular suit hammer cart shrug oval student", + ETHEREUM_DEFAULT_PATH, + "0x604a95C9165Bc95aE016a5299dd7d400dDDBEa9A", + ), + # Metamask + # https://github.com/MetaMask/eth-hd-keyring/blob/79d088e4a73624537e924b3943830526/test/index.js + ( + "finish oppose decorate face calm tragic certain desk hour urge dinosaur mango", + ETHEREUM_DEFAULT_PATH, + "0x1c96099350f13D558464eC79B9bE4445AA0eF579", + ), + ( + "finish oppose decorate face calm tragic certain desk hour urge dinosaur mango", + "m/44'/60'/0'/0/1", # 2nd account index in path + "0x1b00AeD43a693F3a957F9FeB5cC08AFA031E37a0", + ), +]) +def test_account_derivation(mnemonic, account_path, expected_address): + a = Account.from_mnemonic(mnemonic, account_path=account_path) + assert a.address == expected_address + + +def test_account_restore(): + a1, mnemonic = Account.create_with_mnemonic(num_words=24, passphrase="TESTING") + a2 = Account.from_mnemonic(mnemonic, passphrase="TESTING") + assert a1.address == a2.address + + +def test_bad_passphrase(): + a1, mnemonic = Account.create_with_mnemonic(passphrase="My passphrase") + a2 = Account.from_mnemonic(mnemonic, passphrase="Not my passphrase") + assert a1.address != a2.address + + +def test_incorrect_size(): + with pytest.raises(ValidationError, match="Language not detected .*"): + Account.from_mnemonic("this is not a seed phrase") + + +def test_malformed_seed(): + with pytest.raises(ValidationError, match=".* not a valid BIP39 mnemonic phrase!"): + # Missing 12th word + Account.from_mnemonic("into trim cross then helmet popular suit hammer cart shrug oval") + + +def test_incorrect_checksum(): + with pytest.raises(ValidationError, match=".* not a valid BIP39 mnemonic phrase!"): + # Moved 12th word of valid phrase to be 1st + Account.from_mnemonic( + "student into trim cross then helmet popular suit hammer cart shrug oval" + ) + + +def test_incorrect_num_words(): + with pytest.raises(ValidationError, match="Invalid choice for number of words.*"): + Account.create_with_mnemonic(num_words=11) + + +def test_bad_account_path1(): + with pytest.raises(ValidationError, match="Path is not valid.*"): + Account.from_mnemonic( + "finish oppose decorate face calm tragic certain desk hour urge dinosaur mango", + account_path='not an account path' + ) + + +def test_bad_account_path2(): + with pytest.raises(ValidationError, match="Path.*is not valid.*"): + Account.create_with_mnemonic(account_path='m/not/an/account/path') + + +def test_unknown_language(): + with pytest.raises(ValidationError, match="Invalid language choice.*"): + Account.create_with_mnemonic(language="pig latin") diff --git a/tests/core/test_mnemonic.py b/tests/core/test_mnemonic.py index 6c07bba4..d5311e5f 100644 --- a/tests/core/test_mnemonic.py +++ b/tests/core/test_mnemonic.py @@ -83,10 +83,11 @@ def test_expand(lang): m = Mnemonic(lang) # Generates a random set of words, so will never be the same set of words words = m.generate() - for word in words.split(" "): + for word in words.split(" "): # Space delinates in languages not excluded above # BIP39 can support word expansion with as little as 4 characters - for size in range(4, len(word)): - assert m.expand(word[:size + 1]) == word + norm_word = normalize_string(word) + for size in range(4, len(norm_word)): + assert m.expand(norm_word[:size + 1]) == word @pytest.mark.parametrize("lang", Mnemonic.list_languages()) diff --git a/tests/integration/ethers-cli/.gitignore b/tests/integration/ethers-cli/.gitignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/tests/integration/ethers-cli/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/tests/integration/ethers-cli/index.js b/tests/integration/ethers-cli/index.js new file mode 100755 index 00000000..73f6482e --- /dev/null +++ b/tests/integration/ethers-cli/index.js @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +const ethers = require('ethers'); +const yargs = require('yargs'); + +const options = yargs + .usage("Usage: -m ") + .option("m", { + alias: "mnemonic", + describe: "BIP39 Mnemonic seed phrase", + type: "array", + demandOption: true, + }) + .option("l", { + alias: "language", + describe: "Wordlist language used for mnemonic", + type: "String", + }) + .option("p", { + alias: "path", + describe: "HD Path used for derivation", + type: "String", + }) + .argv; + +var wordlist; + +switch(options.language) { + case "english": + wordlist = ethers.wordlists.en; + break; + case "spanish": + wordlist = ethers.wordlists.es; + break; + case "french": + wordlist = ethers.wordlists.fr; + break; + case "italian": + wordlist = ethers.wordlists.it; + break; + case "czech": + wordlist = ethers.wordlists.cz; + break; + case "japanese": + wordlist = ethers.wordlists.ja; + break; + case "korean": + wordlist = ethers.wordlists.ko; + break; + case "chinese_simplified": + wordlist = ethers.wordlists.zh_cn; + break; + case "chinese_traditional": + wordlist = ethers.wordlists.zh_tw; + break; + default: + wordlist = ethers.wordlists.en; +} + +// If specified, use the given path, else default to Ethereum +const path = options.path ? options.path : "m/44'/60'/0'/0/0"; + +const account = ethers.Wallet.fromMnemonic( + options.mnemonic.join(" "), + path, + wordlist, +); + +console.log(account.address); diff --git a/tests/integration/ethers-cli/package-lock.json b/tests/integration/ethers-cli/package-lock.json new file mode 100644 index 00000000..aeef64f0 --- /dev/null +++ b/tests/integration/ethers-cli/package-lock.json @@ -0,0 +1,702 @@ +{ + "name": "ethers-cli", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ethersproject/abi": { + "version": "5.0.0-beta.145", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.145.tgz", + "integrity": "sha512-buO1aiUe408qo8guMzwvzezUVKmQyhM21sbNaG8XrktrnxTNLvRghN1NYbtQi8Ov0ZT+P93VPz1whKu1Y2s2Xg==", + "requires": { + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/hash": ">=5.0.0-beta.128", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/strings": ">=5.0.0-beta.130" + } + }, + "@ethersproject/abstract-provider": { + "version": "5.0.0-beta.138", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.0-beta.138.tgz", + "integrity": "sha512-bIEBUMm62TxTF+zHOUHPfMQLf3gvN5cVR1Gyv5/LVuDz3UESgFTBHBpFLHPlW2/RLHDo7K0jx16a38vs6/r2gQ==", + "requires": { + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/networks": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/transactions": ">=5.0.0-beta.128", + "@ethersproject/web": ">=5.0.0-beta.129" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.0.0-beta.140", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.0-beta.140.tgz", + "integrity": "sha512-fROSxYPhtXqxK1y6/mJMpCUcjfUzCSuqNfACcPy2pwoOHMz1hsqS7m7HOEXy0HGAsQPw4fVuo4fywfA+Q62kmQ==", + "requires": { + "@ethersproject/abstract-provider": ">=5.0.0-beta.131", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131" + } + }, + "@ethersproject/address": { + "version": "5.0.0-beta.134", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.0-beta.134.tgz", + "integrity": "sha512-FHhUVJTUIg2pXvOOhIt8sB1cQbcwrzZKzf9CPV7JM1auli20nGoYhyMFYGK7u++GXzTMJduIkU1OwlIBupewDw==", + "requires": { + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/rlp": ">=5.0.0-beta.126", + "bn.js": "^4.4.0" + } + }, + "@ethersproject/base64": { + "version": "5.0.0-beta.131", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.0-beta.131.tgz", + "integrity": "sha512-pjgZZyDlGpSBkbuO87hnmVrOa92znIt5EIGBW1Mly5Nby8PU4YVwK3WoRP2vGd7hViNVLPCgfbmhh6LQhWK1sg==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129" + } + }, + "@ethersproject/basex": { + "version": "5.0.0-beta.132", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.0-beta.132.tgz", + "integrity": "sha512-BlTGjIW5O03Tl3cVrBWPYnSnhEdz7h3sAely82xDZPutUw9PyPy/PF7IN19iVNgv5ZKQlaDmQZ6M2OGzVOuIPw==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131" + } + }, + "@ethersproject/bignumber": { + "version": "5.0.0-beta.135", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.0-beta.135.tgz", + "integrity": "sha512-7Tw2NgHzK7o+70bwyoaIZCbRycz+saWNU0sLOYnis3qYXwYsdTL+Rm0PMGA2v4jyHJt7BPS2pxGww+akVXbX+w==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "bn.js": "^4.4.0" + } + }, + "@ethersproject/bytes": { + "version": "5.0.0-beta.136", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.0-beta.136.tgz", + "integrity": "sha512-yoi5Ul16ScMHVNsf+oCDGaAnj+rtXxITcneXPeDl8h0rk1VNIqb1WKKvooD5WtM0oAglyauuDahHIF+4+5G/Sg==", + "requires": { + "@ethersproject/logger": ">=5.0.0-beta.129" + } + }, + "@ethersproject/constants": { + "version": "5.0.0-beta.133", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.0-beta.133.tgz", + "integrity": "sha512-VCTpk3AF00mlWQw1vg+fI6qCo0qO5EVWK574t4HNBKW6X748jc9UJPryKUz9JgZ64ZQupyLM92wHilsG/YTpNQ==", + "requires": { + "@ethersproject/bignumber": ">=5.0.0-beta.130" + } + }, + "@ethersproject/contracts": { + "version": "5.0.0-beta.143", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.0-beta.143.tgz", + "integrity": "sha512-xjWNlnbhfAkWxBW1ICi6l/O9iplf6GW8IlN57DddERCuzJnj3t2g3PinVTacH27ySqApnWF2FbFQIf0BRYp5hQ==", + "requires": { + "@ethersproject/abi": ">=5.0.0-beta.137", + "@ethersproject/abstract-provider": ">=5.0.0-beta.131", + "@ethersproject/abstract-signer": ">=5.0.0-beta.132", + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/transactions": ">=5.0.0-beta.128" + } + }, + "@ethersproject/hash": { + "version": "5.0.0-beta.133", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.0-beta.133.tgz", + "integrity": "sha512-tfF11QxFlJCy92rMtUZ0kImchWhlYXkN5Gj5cYfTcCdWEUKwNq1LljDnlrjV2JabO6s5enb8uiUj4RBTo2+Rgw==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/strings": ">=5.0.0-beta.130" + } + }, + "@ethersproject/hdnode": { + "version": "5.0.0-beta.137", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.0-beta.137.tgz", + "integrity": "sha512-TDe57vm/tndbaSKi/NRgC0uAp4uVr60LurTAw+u6mG5ihZg9mlYgr15GxOXWTRiJfa3V3kQD8VsTpzlNMYHViw==", + "requires": { + "@ethersproject/abstract-signer": ">=5.0.0-beta.132", + "@ethersproject/basex": ">=5.0.0-beta.127", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/pbkdf2": ">=5.0.0-beta.127", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/sha2": ">=5.0.0-beta.129", + "@ethersproject/signing-key": ">=5.0.0-beta.129", + "@ethersproject/strings": ">=5.0.0-beta.130", + "@ethersproject/transactions": ">=5.0.0-beta.128", + "@ethersproject/wordlists": ">=5.0.0-beta.128" + } + }, + "@ethersproject/json-wallets": { + "version": "5.0.0-beta.136", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.0-beta.136.tgz", + "integrity": "sha512-hO10rNY+m39lTjP6TWb91+rGx1flsde/LP5Ajx/mXeBwx2pLm8dWAv7h7XdymCeUvFgwVdDx2jAskm+9u1AN1Q==", + "requires": { + "@ethersproject/abstract-signer": ">=5.0.0-beta.132", + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/hdnode": ">=5.0.0-beta.130", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/pbkdf2": ">=5.0.0-beta.127", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/random": ">=5.0.0-beta.128", + "@ethersproject/strings": ">=5.0.0-beta.130", + "@ethersproject/transactions": ">=5.0.0-beta.128", + "aes-js": "3.0.0", + "scrypt-js": "3.0.0", + "uuid": "2.0.1" + } + }, + "@ethersproject/keccak256": { + "version": "5.0.0-beta.131", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.0-beta.131.tgz", + "integrity": "sha512-KQnqMwGV0IMOjAr/UTFO8DuLrmN1uaMvcV3zh9hiXhh3rCuY+WXdeUh49w1VQ94kBKmaP0qfGb7z4SdhUWUHjw==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "js-sha3": "0.5.7" + } + }, + "@ethersproject/logger": { + "version": "5.0.0-beta.134", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.0-beta.134.tgz", + "integrity": "sha512-0nqZqf12/dCNfUhmpSvJweW6xQk9ixqgo/Fy3bVMbGKbuzezZtKPphGB5ibspvimWrVK7U6jLBTKHgRQKjU8Lg==" + }, + "@ethersproject/networks": { + "version": "5.0.0-beta.135", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.0-beta.135.tgz", + "integrity": "sha512-9wesbAlsewNe0dU8B/lhK449GZml+08Opjf6nFpcV8BwWlYnPLs7EnOsK3GpMM0KDPZlksVYltyq+X1B7YxOcA==", + "requires": { + "@ethersproject/logger": ">=5.0.0-beta.129" + } + }, + "@ethersproject/pbkdf2": { + "version": "5.0.0-beta.133", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.0-beta.133.tgz", + "integrity": "sha512-dOOiJSuPyQWoTexbXugVQY75vZbsediR+d1UhEfnPkKavAuks/o5mRyKYSO/EXY0qwWH01xCUEjg0RWGm93kCQ==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/sha2": ">=5.0.0-beta.129" + } + }, + "@ethersproject/properties": { + "version": "5.0.0-beta.137", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.0-beta.137.tgz", + "integrity": "sha512-AcvoVmV0aXixa7SxaPj237OAIEXl/UMJf4vl2yFNzWjf77mMyZaZoKLLOh2zes++mLeQ3EJEIebSWFm06L5NuA==", + "requires": { + "@ethersproject/logger": ">=5.0.0-beta.129" + } + }, + "@ethersproject/providers": { + "version": "5.0.0-beta.153", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.0-beta.153.tgz", + "integrity": "sha512-FJ/dNM5fj25m1XAEJzdC1B6GM9On3eRn/Vls6cUcSBWTOfKsTRf0uRSkBq1kNbPdx3lF0zQT4xIVmCCklA+DaQ==", + "requires": { + "@ethersproject/abstract-provider": ">=5.0.0-beta.131", + "@ethersproject/abstract-signer": ">=5.0.0-beta.132", + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/hash": ">=5.0.0-beta.128", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/networks": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/random": ">=5.0.0-beta.128", + "@ethersproject/rlp": ">=5.0.0-beta.126", + "@ethersproject/strings": ">=5.0.0-beta.130", + "@ethersproject/transactions": ">=5.0.0-beta.128", + "@ethersproject/web": ">=5.0.0-beta.129" + } + }, + "@ethersproject/random": { + "version": "5.0.0-beta.133", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.0-beta.133.tgz", + "integrity": "sha512-walmaJK9MWy02I0SAHmv5Dg8His0Vn4x/ehqlu081z5gpm0WRo9H+3tlhaHQzAI0aK6B3mRV0bsG+PvWRh41Jg==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/logger": ">=5.0.0-beta.129" + } + }, + "@ethersproject/rlp": { + "version": "5.0.0-beta.131", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.0-beta.131.tgz", + "integrity": "sha512-sUJUGbywlnuk2frkSWzWiGenTrwOnrKQaNKJqjCGmK35x0WIzcR4/1gC6jWa0hpWJT6Seq6J6SCT5CS+ZWCFNw==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129" + } + }, + "@ethersproject/sha2": { + "version": "5.0.0-beta.134", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.0-beta.134.tgz", + "integrity": "sha512-N/4c+erhRzfGSgOa8vSDUsorL/k/3NNubR5mwrthufMyvmfAsZDizkMPnRqC4HLy39jSmD35c8FFAEC8ebTd0w==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/logger": ">=5.0.0-beta.129", + "hash.js": "1.1.3" + }, + "dependencies": { + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + } + } + }, + "@ethersproject/signing-key": { + "version": "5.0.0-beta.135", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.0-beta.135.tgz", + "integrity": "sha512-D4w5svi8F8eYs+LTuroKzOR8le6ZKtmH/mDmtuz15vz3XdOkLPGVne5mqqqLJd8APBnOEDtsAqmg7ZCrAk8Mag==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "elliptic": "6.5.2" + } + }, + "@ethersproject/solidity": { + "version": "5.0.0-beta.131", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.0-beta.131.tgz", + "integrity": "sha512-i5vuj2CXGMkVPo08bmElC2cvhjRDNRZZ8nzvx2WCi75Zh42xD0XNV77E9ZLYgS0WoZSiAi/F71nXSBnM7FAqJg==", + "requires": { + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/sha2": ">=5.0.0-beta.129", + "@ethersproject/strings": ">=5.0.0-beta.130" + } + }, + "@ethersproject/strings": { + "version": "5.0.0-beta.136", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.0-beta.136.tgz", + "integrity": "sha512-Hb9RvTrgGcOavHvtQZz+AuijB79BO3g1cfF2MeMfCU9ID4j3mbZv/olzDMS2pK9r4aERJpAS94AmlWzCgoY2LQ==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/logger": ">=5.0.0-beta.129" + } + }, + "@ethersproject/transactions": { + "version": "5.0.0-beta.134", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.0-beta.134.tgz", + "integrity": "sha512-06VxNv6UHds153Ey3WJ2YDPReNkwmIm8fyuJOXRZ6IoYh5ns5CfR4fkmHSBtw7+/KIVjmRoMQZ4Yg/tcGmzz0A==", + "requires": { + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/rlp": ">=5.0.0-beta.126", + "@ethersproject/signing-key": ">=5.0.0-beta.129" + } + }, + "@ethersproject/units": { + "version": "5.0.0-beta.132", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.0-beta.132.tgz", + "integrity": "sha512-3GZDup1uTydvqaP5wpwoRF36irp6kx/gd3buPG+aoGWLPCoPjyk76OiGoxNQKfEaynOdZ7zG2lM8WevlBDJ57g==", + "requires": { + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/logger": ">=5.0.0-beta.129" + } + }, + "@ethersproject/wallet": { + "version": "5.0.0-beta.137", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.0-beta.137.tgz", + "integrity": "sha512-L5Ms3Rdq5LYpTHXRqZ17rdIKlbVlRUbncHtp1bMa+W7VGZJoQEWSLXtqN+q0u6Lx+w2Cg1sHvXqL+i66TRhDkw==", + "requires": { + "@ethersproject/abstract-provider": ">=5.0.0-beta.131", + "@ethersproject/abstract-signer": ">=5.0.0-beta.132", + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/hash": ">=5.0.0-beta.128", + "@ethersproject/hdnode": ">=5.0.0-beta.130", + "@ethersproject/json-wallets": ">=5.0.0-beta.129", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/random": ">=5.0.0-beta.128", + "@ethersproject/signing-key": ">=5.0.0-beta.129", + "@ethersproject/transactions": ">=5.0.0-beta.128", + "@ethersproject/wordlists": ">=5.0.0-beta.128" + } + }, + "@ethersproject/web": { + "version": "5.0.0-beta.135", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.0-beta.135.tgz", + "integrity": "sha512-5g0jGtQvLeU/O0KTlp9cqm5PpuDUZzopJaO8LxZpFW9t+5uVuBcJe8uoA8z+OsAnsRKPc6bGBc9esrWEW0hKLw==", + "requires": { + "@ethersproject/base64": ">=5.0.0-beta.126", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/strings": ">=5.0.0-beta.130", + "cross-fetch": "3.0.4" + } + }, + "@ethersproject/wordlists": { + "version": "5.0.0-beta.135", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.0-beta.135.tgz", + "integrity": "sha512-hGwIme0in4cJrhdumTJVc1OLEa7S/oxALMOION4C+31yKFdWfX00dOXi6aqokWkGaUQXvmHz4r9/GhfqzoB2Qg==", + "requires": { + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/hash": ">=5.0.0-beta.128", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/strings": ">=5.0.0-beta.130" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "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==", + "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==" + }, + "cross-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.4.tgz", + "integrity": "sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw==", + "requires": { + "node-fetch": "2.6.0", + "whatwg-fetch": "3.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "elliptic": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "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" + } + }, + "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==" + }, + "ethers": { + "version": "5.0.0-beta.173", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.0-beta.173.tgz", + "integrity": "sha512-wAj6vYXL6Kgm6baLCZRJukMo/4DmHe7lMd0xLZhtc7PJbgJwiTGwjfpGxLSoj0EWFh69o0TXVQ0PDNgvfWjDyw==", + "requires": { + "@ethersproject/abi": ">=5.0.0-beta.137", + "@ethersproject/abstract-provider": ">=5.0.0-beta.131", + "@ethersproject/abstract-signer": ">=5.0.0-beta.132", + "@ethersproject/address": ">=5.0.0-beta.128", + "@ethersproject/base64": ">=5.0.0-beta.126", + "@ethersproject/bignumber": ">=5.0.0-beta.130", + "@ethersproject/bytes": ">=5.0.0-beta.129", + "@ethersproject/constants": ">=5.0.0-beta.128", + "@ethersproject/contracts": ">=5.0.0-beta.137", + "@ethersproject/hash": ">=5.0.0-beta.128", + "@ethersproject/hdnode": ">=5.0.0-beta.130", + "@ethersproject/json-wallets": ">=5.0.0-beta.129", + "@ethersproject/keccak256": ">=5.0.0-beta.127", + "@ethersproject/logger": ">=5.0.0-beta.129", + "@ethersproject/networks": ">=5.0.0-beta.129", + "@ethersproject/pbkdf2": ">=5.0.0-beta.127", + "@ethersproject/properties": ">=5.0.0-beta.131", + "@ethersproject/providers": ">=5.0.0-beta.141", + "@ethersproject/random": ">=5.0.0-beta.128", + "@ethersproject/rlp": ">=5.0.0-beta.126", + "@ethersproject/sha2": ">=5.0.0-beta.129", + "@ethersproject/signing-key": ">=5.0.0-beta.129", + "@ethersproject/solidity": ">=5.0.0-beta.126", + "@ethersproject/strings": ">=5.0.0-beta.130", + "@ethersproject/transactions": ">=5.0.0-beta.128", + "@ethersproject/units": ">=5.0.0-beta.127", + "@ethersproject/wallet": ">=5.0.0-beta.130", + "@ethersproject/web": ">=5.0.0-beta.129", + "@ethersproject/wordlists": ">=5.0.0-beta.128" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "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==" + }, + "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-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==" + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.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=" + }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "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==", + "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==" + }, + "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==" + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "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==" + }, + "scrypt-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.0.tgz", + "integrity": "sha512-7CC7aufwukEvqdmllR0ny0QaSg0+S22xKXrXz3ZahaV6J+fgD2YAtrjtImuoDWog17/Ty9Q4HBmnXEXJ3JkfQA==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "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==", + "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==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "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==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "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==" + }, + "yargs": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.1.0.tgz", + "integrity": "sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==", + "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": "^16.1.0" + } + }, + "yargs-parser": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", + "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/tests/integration/ethers-cli/package.json b/tests/integration/ethers-cli/package.json new file mode 100644 index 00000000..06782eeb --- /dev/null +++ b/tests/integration/ethers-cli/package.json @@ -0,0 +1,18 @@ +{ + "name": "ethers-cli", + "version": "1.0.0", + "description": "", + "main": "index.js", + "bin": { + "ethers-cli": "./index.js" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "ethers": "^5.0.0-beta.173 ", + "yargs": "^15.1.0" + } +} diff --git a/tests/integration/ethers-cli/setup_node_v12.sh b/tests/integration/ethers-cli/setup_node_v12.sh new file mode 100644 index 00000000..88853508 --- /dev/null +++ b/tests/integration/ethers-cli/setup_node_v12.sh @@ -0,0 +1,328 @@ +#!/bin/bash + +# Discussion, issues and change requests at: +# https://github.com/nodesource/distributions +# +# Script to install the NodeSource Node.js 12.x repo onto a +# Debian or Ubuntu system. +# +# Run as root or insert `sudo -E` before `bash`: +# +# curl -sL https://deb.nodesource.com/setup_12.x | bash - +# or +# wget -qO- https://deb.nodesource.com/setup_12.x | bash - +# +# CONTRIBUTIONS TO THIS SCRIPT +# +# This script is built from a template in +# https://github.com/nodesource/distributions/tree/master/deb/src +# please don't submit pull requests against the built scripts. +# + + +export DEBIAN_FRONTEND=noninteractive +SCRSUFFIX="_12.x" +NODENAME="Node.js 12.x" +NODEREPO="node_12.x" +NODEPKG="nodejs" + +print_status() { + echo + echo "## $1" + echo +} + +if test -t 1; then # if terminal + ncolors=$(which tput > /dev/null && tput colors) # supports color + if test -n "$ncolors" && test $ncolors -ge 8; then + termcols=$(tput cols) + bold="$(tput bold)" + underline="$(tput smul)" + standout="$(tput smso)" + normal="$(tput sgr0)" + black="$(tput setaf 0)" + red="$(tput setaf 1)" + green="$(tput setaf 2)" + yellow="$(tput setaf 3)" + blue="$(tput setaf 4)" + magenta="$(tput setaf 5)" + cyan="$(tput setaf 6)" + white="$(tput setaf 7)" + fi +fi + +print_bold() { + title="$1" + text="$2" + + echo + echo "${red}================================================================================${normal}" + echo "${red}================================================================================${normal}" + echo + echo -e " ${bold}${yellow}${title}${normal}" + echo + echo -en " ${text}" + echo + echo "${red}================================================================================${normal}" + echo "${red}================================================================================${normal}" +} + +bail() { + echo 'Error executing command, exiting' + exit 1 +} + +exec_cmd_nobail() { + echo "+ $1" + bash -c "$1" +} + +exec_cmd() { + exec_cmd_nobail "$1" || bail +} + +node_deprecation_warning() { + if [[ "X${NODENAME}" == "Xio.js 1.x" || + "X${NODENAME}" == "Xio.js 2.x" || + "X${NODENAME}" == "Xio.js 3.x" || + "X${NODENAME}" == "XNode.js 0.10" || + "X${NODENAME}" == "XNode.js 0.12" || + "X${NODENAME}" == "XNode.js 4.x LTS Argon" || + "X${NODENAME}" == "XNode.js 5.x" || + "X${NODENAME}" == "XNode.js 6.x LTS Boron" || + "X${NODENAME}" == "XNode.js 7.x" || + "X${NODENAME}" == "XNode.js 8.x LTS Carbon" || + "X${NODENAME}" == "XNode.js 9.x" || + "X${NODENAME}" == "XNode.js 11.x" ]]; then + + print_bold \ +" DEPRECATION WARNING " "\ +${bold}${NODENAME} is no longer actively supported!${normal} + + ${bold}You will not receive security or critical stability updates${normal} for this version. + + You should migrate to a supported version of Node.js as soon as possible. + Use the installation script that corresponds to the version of Node.js you + wish to install. e.g. + + * ${green}https://deb.nodesource.com/setup_10.x — Node.js 10 LTS \"Dubnium\"${normal} (recommended) + * ${green}https://deb.nodesource.com/setup_12.x — Node.js 12 LTS \"Erbium\"${normal} + + Please see ${bold}https://github.com/nodejs/Release${normal} for details about which + version may be appropriate for you. + + The ${bold}NodeSource${normal} Node.js distributions repository contains + information both about supported versions of Node.js and supported Linux + distributions. To learn more about usage, see the repository: + ${bold}https://github.com/nodesource/distributions${normal} +" + echo + echo "Continuing in 20 seconds ..." + echo + sleep 20 + fi +} + +script_deprecation_warning() { + if [ "X${SCRSUFFIX}" == "X" ]; then + print_bold \ +" SCRIPT DEPRECATION WARNING " "\ +This script, located at ${bold}https://deb.nodesource.com/setup${normal}, used to + install Node.js 0.10, is deprecated and will eventually be made inactive. + + You should use the script that corresponds to the version of Node.js you + wish to install. e.g. + + * ${green}https://deb.nodesource.com/setup_10.x — Node.js 10 LTS \"Dubnium\"${normal} (recommended) + * ${green}https://deb.nodesource.com/setup_12.x — Node.js 12 LTS \"Erbium\"${normal} + Please see ${bold}https://github.com/nodejs/Release${normal} for details about which + version may be appropriate for you. + + The ${bold}NodeSource${normal} Node.js Linux distributions GitHub repository contains + information about which versions of Node.js and which Linux distributions + are supported and how to use the install scripts. + ${bold}https://github.com/nodesource/distributions${normal} +" + + echo + echo "Continuing in 20 seconds (press Ctrl-C to abort) ..." + echo + sleep 20 + fi +} + +setup() { + +script_deprecation_warning +node_deprecation_warning + +print_status "Installing the NodeSource ${NODENAME} repo..." + +if $(uname -m | grep -Eq ^armv6); then + print_status "You appear to be running on ARMv6 hardware. Unfortunately this is not currently supported by the NodeSource Linux distributions. Please use the 'linux-armv6l' binary tarballs available directly from nodejs.org for Node.js 4 and later." + exit 1 +fi + +PRE_INSTALL_PKGS="" + +# Check that HTTPS transport is available to APT +# (Check snaked from: https://get.docker.io/ubuntu/) + +if [ ! -e /usr/lib/apt/methods/https ]; then + PRE_INSTALL_PKGS="${PRE_INSTALL_PKGS} apt-transport-https" +fi + +if [ ! -x /usr/bin/lsb_release ]; then + PRE_INSTALL_PKGS="${PRE_INSTALL_PKGS} lsb-release" +fi + +if [ ! -x /usr/bin/curl ] && [ ! -x /usr/bin/wget ]; then + PRE_INSTALL_PKGS="${PRE_INSTALL_PKGS} curl" +fi + +# Used by apt-key to add new keys + +if [ ! -x /usr/bin/gpg ]; then + PRE_INSTALL_PKGS="${PRE_INSTALL_PKGS} gnupg" +fi + +# Populating Cache +print_status "Populating apt-get cache..." +exec_cmd 'apt-get update' + +if [ "X${PRE_INSTALL_PKGS}" != "X" ]; then + print_status "Installing packages required for setup:${PRE_INSTALL_PKGS}..." + # This next command needs to be redirected to /dev/null or the script will bork + # in some environments + exec_cmd "apt-get install -y${PRE_INSTALL_PKGS} > /dev/null 2>&1" +fi + +IS_PRERELEASE=$(lsb_release -d | grep 'Ubuntu .*development' >& /dev/null; echo $?) +if [[ $IS_PRERELEASE -eq 0 ]]; then + print_status "Your distribution, identified as \"$(lsb_release -d -s)\", is a pre-release version of Ubuntu. NodeSource does not maintain official support for Ubuntu versions until they are formally released. You can try using the manual installation instructions available at https://github.com/nodesource/distributions and use the latest supported Ubuntu version name as the distribution identifier, although this is not guaranteed to work." + exit 1 +fi + +DISTRO=$(lsb_release -c -s) + +check_alt() { + if [ "X${DISTRO}" == "X${2}" ]; then + echo + echo "## You seem to be using ${1} version ${DISTRO}." + echo "## This maps to ${3} \"${4}\"... Adjusting for you..." + DISTRO="${4}" + fi +} + +check_alt "SolydXK" "solydxk-9" "Debian" "stretch" +check_alt "Kali" "sana" "Debian" "jessie" +check_alt "Kali" "kali-rolling" "Debian" "jessie" +check_alt "Sparky Linux" "Tyche" "Debian" "stretch" +check_alt "Sparky Linux" "Nibiru" "Debian" "buster" +check_alt "MX Linux 17" "Horizon" "Debian" "stretch" +check_alt "MX Linux 18" "Continuum" "Debian" "stretch" +check_alt "MX Linux 19" "patito feo" "Debian" "buster" +check_alt "Linux Mint" "maya" "Ubuntu" "precise" +check_alt "Linux Mint" "qiana" "Ubuntu" "trusty" +check_alt "Linux Mint" "rafaela" "Ubuntu" "trusty" +check_alt "Linux Mint" "rebecca" "Ubuntu" "trusty" +check_alt "Linux Mint" "rosa" "Ubuntu" "trusty" +check_alt "Linux Mint" "sarah" "Ubuntu" "xenial" +check_alt "Linux Mint" "serena" "Ubuntu" "xenial" +check_alt "Linux Mint" "sonya" "Ubuntu" "xenial" +check_alt "Linux Mint" "sylvia" "Ubuntu" "xenial" +check_alt "Linux Mint" "tara" "Ubuntu" "bionic" +check_alt "Linux Mint" "tessa" "Ubuntu" "bionic" +check_alt "Linux Mint" "tina" "Ubuntu" "bionic" +check_alt "Linux Mint" "tricia" "Ubuntu" "bionic" +check_alt "LMDE" "betsy" "Debian" "jessie" +check_alt "LMDE" "cindy" "Debian" "stretch" +check_alt "elementaryOS" "luna" "Ubuntu" "precise" +check_alt "elementaryOS" "freya" "Ubuntu" "trusty" +check_alt "elementaryOS" "loki" "Ubuntu" "xenial" +check_alt "elementaryOS" "juno" "Ubuntu" "bionic" +check_alt "elementaryOS" "hera" "Ubuntu" "bionic" +check_alt "Trisquel" "toutatis" "Ubuntu" "precise" +check_alt "Trisquel" "belenos" "Ubuntu" "trusty" +check_alt "Trisquel" "flidas" "Ubuntu" "xenial" +check_alt "Uruk GNU/Linux" "lugalbanda" "Ubuntu" "xenial" +check_alt "BOSS" "anokha" "Debian" "wheezy" +check_alt "BOSS" "anoop" "Debian" "jessie" +check_alt "BOSS" "drishti" "Debian" "stretch" +check_alt "bunsenlabs" "bunsen-hydrogen" "Debian" "jessie" +check_alt "bunsenlabs" "helium" "Debian" "stretch" +check_alt "Tanglu" "chromodoris" "Debian" "jessie" +check_alt "PureOS" "green" "Debian" "sid" +check_alt "Devuan" "jessie" "Debian" "jessie" +check_alt "Devuan" "ascii" "Debian" "stretch" +check_alt "Devuan" "beowulf" "Debian" "buster" +check_alt "Devuan" "ceres" "Debian" "sid" +check_alt "Deepin" "panda" "Debian" "sid" +check_alt "Deepin" "unstable" "Debian" "sid" +check_alt "Deepin" "stable" "Debian" "buster" +check_alt "Pardus" "onyedi" "Debian" "stretch" +check_alt "Liquid Lemur" "lemur-3" "Debian" "stretch" + +if [ "X${DISTRO}" == "Xdebian" ]; then + print_status "Unknown Debian-based distribution, checking /etc/debian_version..." + NEWDISTRO=$([ -e /etc/debian_version ] && cut -d/ -f1 < /etc/debian_version) + if [ "X${NEWDISTRO}" == "X" ]; then + print_status "Could not determine distribution from /etc/debian_version..." + else + DISTRO=$NEWDISTRO + print_status "Found \"${DISTRO}\" in /etc/debian_version..." + fi +fi + +print_status "Confirming \"${DISTRO}\" is supported..." + +if [ -x /usr/bin/curl ]; then + exec_cmd_nobail "curl -sLf -o /dev/null 'https://deb.nodesource.com/${NODEREPO}/dists/${DISTRO}/Release'" + RC=$? +else + exec_cmd_nobail "wget -qO /dev/null -o /dev/null 'https://deb.nodesource.com/${NODEREPO}/dists/${DISTRO}/Release'" + RC=$? +fi + +if [[ $RC != 0 ]]; then + print_status "Your distribution, identified as \"${DISTRO}\", is not currently supported, please contact NodeSource at https://github.com/nodesource/distributions/issues if you think this is incorrect or would like your distribution to be considered for support" + exit 1 +fi + +if [ -f "/etc/apt/sources.list.d/chris-lea-node_js-$DISTRO.list" ]; then + print_status 'Removing Launchpad PPA Repository for NodeJS...' + + exec_cmd_nobail 'add-apt-repository -y -r ppa:chris-lea/node.js' + exec_cmd "rm -f /etc/apt/sources.list.d/chris-lea-node_js-${DISTRO}.list" +fi + +print_status 'Adding the NodeSource signing key to your keyring...' + +if [ -x /usr/bin/curl ]; then + exec_cmd 'curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -' +else + exec_cmd 'wget -qO- https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -' +fi + +print_status "Creating apt sources list file for the NodeSource ${NODENAME} repo..." + +exec_cmd "echo 'deb https://deb.nodesource.com/${NODEREPO} ${DISTRO} main' > /etc/apt/sources.list.d/nodesource.list" +exec_cmd "echo 'deb-src https://deb.nodesource.com/${NODEREPO} ${DISTRO} main' >> /etc/apt/sources.list.d/nodesource.list" + +print_status 'Running `apt-get update` for you...' + +exec_cmd 'apt-get update' + +print_status """Run \`${bold}sudo apt-get install -y ${NODEPKG}${normal}\` to install ${NODENAME} and npm +## You may also need development tools to build native addons: + sudo apt-get install gcc g++ make +## To install the Yarn package manager, run: + curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - + echo \"deb https://dl.yarnpkg.com/debian/ stable main\" | sudo tee /etc/apt/sources.list.d/yarn.list + sudo apt-get update && sudo apt-get install yarn +""" + +} + +## Defer setup until we have the complete script +setup diff --git a/tests/integration/test_ethers_fuzzing.py b/tests/integration/test_ethers_fuzzing.py new file mode 100644 index 00000000..073b3f44 --- /dev/null +++ b/tests/integration/test_ethers_fuzzing.py @@ -0,0 +1,46 @@ +from hypothesis import ( + given, + settings, + strategies as st, +) +import pytest +import subprocess + +from eth_account import ( + Account, +) +from eth_account.hdaccount.mnemonic import ( + VALID_ENTROPY_SIZES, + Mnemonic, +) + +Account.enable_unaudited_hdwallet_features() + +language_st = st.sampled_from(Mnemonic.list_languages()) + +seed_st = st.binary(min_size=min(VALID_ENTROPY_SIZES), max_size=max(VALID_ENTROPY_SIZES)) \ + .filter(lambda x: len(x) in VALID_ENTROPY_SIZES) \ + .filter(lambda s: int.from_bytes(s, byteorder="big") != 0) + +node_st = st.tuples(st.integers(min_value=0, max_value=2**31 - 1), st.booleans()) +path_st = st.lists(node_st, min_size=0, max_size=10) \ + .map(lambda nodes: list(str(n[0]) + ('' if n[1] else "'") for n in nodes)) \ + .map(lambda nodes: 'm' + ('/' + '/'.join(nodes) if nodes else '')) + + +@given(seed=seed_st, language=language_st, account_path=path_st) +@settings(deadline=1000) +@pytest.mark.compatibility +def test_compatibility(seed, language, account_path): + mnemonic = Mnemonic(language).to_mnemonic(seed) + acct = Account.from_mnemonic(mnemonic, account_path=account_path) + # NOTE Must do `cd tests/integration/ethers-cli && npm install -g . + ethers_cli = subprocess.run( + ['ethers-cli', '-m', mnemonic, '-l', language, '-p', account_path], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + if ethers_cli.stderr: + raise IOError(ethers_cli.stderr.decode("utf-8")) + ethers_address = ethers_cli.stdout.decode("utf-8").strip() + assert acct.address == ethers_address diff --git a/tox.ini b/tox.ini index b216f26d..c6bd9870 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,7 @@ [tox] envlist= py{36,37,38}-core + py{36,37,38}-integration lint doctest @@ -23,6 +24,7 @@ ignore= usedevelop=True commands= core: pytest {posargs:tests/core eth_account} + integration: pytest {posargs:tests/integration eth_account} doctest: make -C {toxinidir}/docs doctest basepython = doctest: python