aboutsummaryrefslogtreecommitdiffstats
path: root/packages/subproviders
diff options
context:
space:
mode:
Diffstat (limited to 'packages/subproviders')
-rw-r--r--packages/subproviders/.npmignore7
-rw-r--r--packages/subproviders/CHANGELOG.json504
-rw-r--r--packages/subproviders/CHANGELOG.md210
-rw-r--r--packages/subproviders/README.md100
-rw-r--r--packages/subproviders/coverage/.gitkeep0
-rw-r--r--packages/subproviders/package.json89
-rw-r--r--packages/subproviders/src/globals.d.ts24
-rw-r--r--packages/subproviders/src/index.ts59
-rw-r--r--packages/subproviders/src/subproviders/base_wallet_subprovider.ts151
-rw-r--r--packages/subproviders/src/subproviders/empty_wallet_subprovider.ts32
-rw-r--r--packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts91
-rw-r--r--packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts46
-rw-r--r--packages/subproviders/src/subproviders/ganache.ts36
-rw-r--r--packages/subproviders/src/subproviders/ledger.ts256
-rw-r--r--packages/subproviders/src/subproviders/metamask_subprovider.ts126
-rw-r--r--packages/subproviders/src/subproviders/mnemonic_wallet.ts164
-rw-r--r--packages/subproviders/src/subproviders/nonce_tracker.ts110
-rw-r--r--packages/subproviders/src/subproviders/private_key_wallet.ts114
-rw-r--r--packages/subproviders/src/subproviders/redundant_subprovider.ts65
-rw-r--r--packages/subproviders/src/subproviders/rpc_subprovider.ts94
-rw-r--r--packages/subproviders/src/subproviders/signer.ts86
-rw-r--r--packages/subproviders/src/subproviders/subprovider.ts70
-rw-r--r--packages/subproviders/src/types.ts138
-rw-r--r--packages/subproviders/src/utils/subprovider_utils.ts15
-rw-r--r--packages/subproviders/src/utils/wallet_utils.ts79
-rw-r--r--packages/subproviders/test/chai_setup.ts11
-rw-r--r--packages/subproviders/test/integration/ledger_subprovider_test.ts205
-rw-r--r--packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts187
-rw-r--r--packages/subproviders/test/unit/ledger_subprovider_test.ts255
-rw-r--r--packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts230
-rw-r--r--packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts149
-rw-r--r--packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts232
-rw-r--r--packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts63
-rw-r--r--packages/subproviders/test/utils/configs.ts5
-rw-r--r--packages/subproviders/test/utils/fixture_data.ts64
-rw-r--r--packages/subproviders/test/utils/ganache_subprovider.ts18
-rw-r--r--packages/subproviders/test/utils/report_callback_errors.ts14
-rw-r--r--packages/subproviders/tsconfig.json8
-rw-r--r--packages/subproviders/tslint.json3
-rw-r--r--packages/subproviders/typedoc-tsconfig.json7
40 files changed, 0 insertions, 4117 deletions
diff --git a/packages/subproviders/.npmignore b/packages/subproviders/.npmignore
deleted file mode 100644
index 44df80fad..000000000
--- a/packages/subproviders/.npmignore
+++ /dev/null
@@ -1,7 +0,0 @@
-.*
-yarn-error.log
-/src/
-/scripts/
-test/
-tsconfig.json
-/lib/src/monorepo_scripts/
diff --git a/packages/subproviders/CHANGELOG.json b/packages/subproviders/CHANGELOG.json
deleted file mode 100644
index 3d5bade1f..000000000
--- a/packages/subproviders/CHANGELOG.json
+++ /dev/null
@@ -1,504 +0,0 @@
-[
- {
- "version": "3.0.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1549547375
- },
- {
- "timestamp": 1549452781,
- "version": "3.0.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "3.0.0",
- "changes": [
- {
- "note": "Upgrade the bignumber.js to v8.0.2",
- "pr": 1517
- },
- {
- "note": "Update ganache-core to v2.3.3",
- "pr": 1518
- }
- ],
- "timestamp": 1549373905
- },
- {
- "timestamp": 1547561734,
- "version": "2.1.11",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1547225310,
- "version": "2.1.10",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1547040760,
- "version": "2.1.9",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "2.1.8",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1544739608
- },
- {
- "version": "2.1.7",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1544570656
- },
- {
- "timestamp": 1543401373,
- "version": "2.1.6",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542821676,
- "version": "2.1.5",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542208198,
- "version": "2.1.4",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542134075,
- "version": "2.1.3",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542028948,
- "version": "2.1.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "2.1.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1541740904
- },
- {
- "version": "2.1.0",
- "changes": [
- {
- "note": "Add `MetamaskSubprovider` to handle inconsistent JSON RPC behaviour",
- "pr": 1102
- },
- {
- "note": "Add support for `eth_signTypedData` in wallets Mnemonic, Private and EthLightWallet",
- "pr": 1102
- },
- {
- "note": "Make web3-provider-engine types a 'dependency' so it's available to users of the library",
- "pr": 1105
- }
- ],
- "timestamp": 1539871071
- },
- {
- "version": "2.0.7",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1538693146
- },
- {
- "timestamp": 1538157789,
- "version": "2.0.6",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1537907159,
- "version": "2.0.5",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1537875740,
- "version": "2.0.4",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1537541580,
- "version": "2.0.3",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1536142250,
- "version": "2.0.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1535377027,
- "version": "2.0.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "2.0.0",
- "changes": [
- {
- "note": "Export types: `PartialTxParams`, `JSONRPCRequestPayloadWithMethod`, `ECSignatureString`, `AccountFetchingConfigs`, `LedgerEthereumClientFactoryAsync`, `OnNextCompleted`, `MnemonicWalletSubproviderConfigs`, LedgerGetAddressResult, `JSONRPCRequestPayload`, `Provider`, `JSONRPCResponsePayload` and `JSONRPCErrorCallback`",
- "pr": 924
- }
- ],
- "timestamp": 1535133899
- },
- {
- "timestamp": 1534210131,
- "version": "1.0.5",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1532619515,
- "version": "1.0.4",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1532614997,
- "version": "1.0.3",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1532605697,
- "version": "1.0.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1532357734,
- "version": "1.0.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1532043000,
- "version": "1.0.0",
- "changes": [
- {
- "note": "Add `RpcSubprovider` with timeout",
- "pr": 874
- },
- {
- "note": "Add `EthLightwalletSubprovider`",
- "pr": 775
- }
- ]
- },
- {
- "timestamp": 1531919263,
- "version": "0.10.6",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1529397769,
- "version": "0.10.4",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1527009133,
- "version": "0.10.3",
- "changes": [
- {
- "note": "Define engine type as Provider in setEngine",
- "pr": 675
- }
- ]
- },
- {
- "timestamp": 1527009133,
- "version": "0.10.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1525477860,
- "version": "0.10.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "0.10.0",
- "changes": [
- {
- "note": "Upgrade web3-provider-engine to 14.0.4",
- "pr": 555
- },
- {
- "note": "Relax `to` validation in base wallet subprovider for transactions that deploy contracts",
- "pr": 555
- }
- ],
- "timestamp": 1525428773
- },
- {
- "version": "0.9.0",
- "changes": [
- {
- "note": "Refactor RedundantRPCSubprovider into RedundantSubprovider where it now accepts an array of subproviders rather then an array of RPC endpoints",
- "pr": 500
- },
- {
- "note": "Add PrivateKeySubprovider and refactor shared functionality into a base wallet subprovider",
- "pr": 506
- },
- {
- "note": "Add MnemonicWalletsubprovider, deprecating our truffle-hdwallet-provider fork",
- "pr": 507
- },
- {
- "note": "Support multiple addresses in ledger and mnemonic wallets",
- "pr": 507
- },
- {
- "note": "Refactors LedgerSubprovider such that explicitly setting the `pathIndex` is no longer required. Simply set the request `from` address as desired",
- "pr": 507
- },
- {
- "note": "Renamed derivationPath to baseDerivationPath.",
- "pr": 507
- }
- ],
- "timestamp": 1523462196
- },
- {
- "timestamp": 1522673609,
- "version": "0.8.4",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "0.8.3",
- "changes": [
- {
- "note": "Introduce `JSONRPCRequestPayloadWithMethod` type",
- "pr": 465
- },
- {
- "note": "Export `ErrorCallback` type.",
- "pr": 465
- }
- ],
- "timestamp": 1522658513
- },
- {
- "version": "0.8.0",
- "changes": [
- {
- "note": "Export `GanacheSubprovider` and `Subprovider`",
- "pr": 426
- },
- {
- "note": "Make all subproviders to derive from `Subprovider`",
- "pr": 426
- },
- {
- "note": "Add types for `NextCallback`, `OnNextCompleted`",
- "pr": 426
- },
- {
- "note": "Ignore `ganache-core` dependency when using package in a browser environment."
- }
- ],
- "timestamp": 1521298800
- },
- {
- "version": "0.7.0",
- "changes": [
- {
- "note": "Updated legerco packages. Removed node-hid package as a dependency and make it an optional dependency. It is still used in integration tests but is causing problems for users on Linux distros.",
- "pr": 437
- }
- ],
- "timestamp": 1520434800
- },
- {
- "version": "0.6.0",
- "changes": [
- {
- "note": "Move web3 types from being a devDep to a dep since one cannot use this package without it",
- "pr": 429
- },
- {
- "note": "Add `numberOfAccounts` param to `LedgerSubprovider` method `getAccountsAsync`",
- "pr": 432
- }
- ],
- "timestamp": 1520089200
- },
- {
- "version": "0.5.0",
- "changes": [
- {
- "note": "Add EmptyWalletSubprovider and FakeGasEstimateSubprovider",
- "pr": 392
- }
- ],
- "timestamp": 1518706800
- },
- {
- "version": "0.4.1",
- "changes": [
- {
- "note": "Fix publishing issue where .npmignore was not properly excluding undesired content",
- "pr": 389
- }
- ],
- "timestamp": 1518102000
- },
- {
- "version": "0.4.0",
- "changes": [
- {
- "note": "Added NonceTrackerSubprovider",
- "pr": 355
- },
- {
- "note": "InjectedWeb3Subprovider accepts a Provider in the constructor, previously it was a Web3 object",
- "pr": 363
- }
- ],
- "timestamp": 1517929200
- },
- {
- "version": "0.3.6",
- "changes": [
- {
- "note": "Return a transaction hash from `_sendTransactionAsync`",
- "pr": 303
- }
- ],
- "timestamp": 1517065200
- },
- {
- "version": "0.3.0",
- "changes": [
- {
- "note": "Allow LedgerSubprovider to handle `eth_sign` in addition to `personal_sign` RPC requests"
- }
- ],
- "timestamp": 1514386800
- },
- {
- "version": "0.2.0",
- "changes": [
- {
- "note": "Improve the performance of address fetching",
- "pr": 271
- }
- ],
- "timestamp": 1513695600
- }
-]
diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md
deleted file mode 100644
index b3dfa757a..000000000
--- a/packages/subproviders/CHANGELOG.md
+++ /dev/null
@@ -1,210 +0,0 @@
-<!--
-changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
-Edit the package's CHANGELOG.json file only.
--->
-
-CHANGELOG
-
-## v3.0.2 - _February 7, 2019_
-
- * Dependencies updated
-
-## v3.0.1 - _February 6, 2019_
-
- * Dependencies updated
-
-## v3.0.0 - _February 5, 2019_
-
- * Upgrade the bignumber.js to v8.0.2 (#1517)
- * Update ganache-core to v2.3.3 (#1518)
-
-## v2.1.11 - _January 15, 2019_
-
- * Dependencies updated
-
-## v2.1.10 - _January 11, 2019_
-
- * Dependencies updated
-
-## v2.1.9 - _January 9, 2019_
-
- * Dependencies updated
-
-## v2.1.8 - _December 13, 2018_
-
- * Dependencies updated
-
-## v2.1.7 - _December 11, 2018_
-
- * Dependencies updated
-
-## v2.1.6 - _November 28, 2018_
-
- * Dependencies updated
-
-## v2.1.5 - _November 21, 2018_
-
- * Dependencies updated
-
-## v2.1.4 - _November 14, 2018_
-
- * Dependencies updated
-
-## v2.1.3 - _November 13, 2018_
-
- * Dependencies updated
-
-## v2.1.2 - _November 12, 2018_
-
- * Dependencies updated
-
-## v2.1.1 - _November 9, 2018_
-
- * Dependencies updated
-
-## v2.1.0 - _October 18, 2018_
-
- * Add `MetamaskSubprovider` to handle inconsistent JSON RPC behaviour (#1102)
- * Add support for `eth_signTypedData` in wallets Mnemonic, Private and EthLightWallet (#1102)
- * Make web3-provider-engine types a 'dependency' so it's available to users of the library (#1105)
-
-## v2.0.7 - _October 4, 2018_
-
- * Dependencies updated
-
-## v2.0.6 - _September 28, 2018_
-
- * Dependencies updated
-
-## v2.0.5 - _September 25, 2018_
-
- * Dependencies updated
-
-## v2.0.4 - _September 25, 2018_
-
- * Dependencies updated
-
-## v2.0.3 - _September 21, 2018_
-
- * Dependencies updated
-
-## v2.0.2 - _September 5, 2018_
-
- * Dependencies updated
-
-## v2.0.1 - _August 27, 2018_
-
- * Dependencies updated
-
-## v2.0.0 - _August 24, 2018_
-
- * Export types: `PartialTxParams`, `JSONRPCRequestPayloadWithMethod`, `ECSignatureString`, `AccountFetchingConfigs`, `LedgerEthereumClientFactoryAsync`, `OnNextCompleted`, `MnemonicWalletSubproviderConfigs`, LedgerGetAddressResult, `JSONRPCRequestPayload`, `Provider`, `JSONRPCResponsePayload` and `JSONRPCErrorCallback` (#924)
-
-## v1.0.5 - _August 14, 2018_
-
- * Dependencies updated
-
-## v1.0.4 - _July 26, 2018_
-
- * Dependencies updated
-
-## v1.0.3 - _July 26, 2018_
-
- * Dependencies updated
-
-## v1.0.2 - _July 26, 2018_
-
- * Dependencies updated
-
-## v1.0.1 - _July 23, 2018_
-
- * Dependencies updated
-
-## v1.0.0 - _July 19, 2018_
-
- * Add `RpcSubprovider` with timeout (#874)
- * Add `EthLightwalletSubprovider` (#775)
-
-## v0.10.6 - _July 18, 2018_
-
- * Dependencies updated
-
-## v0.10.4 - _June 19, 2018_
-
- * Dependencies updated
-
-## v0.10.3 - _May 22, 2018_
-
- * Define engine type as Provider in setEngine (#675)
-
-## v0.10.2 - _May 22, 2018_
-
- * Dependencies updated
-
-## v0.10.1 - _May 4, 2018_
-
- * Dependencies updated
-
-## v0.10.0 - _May 4, 2018_
-
- * Upgrade web3-provider-engine to 14.0.4 (#555)
- * Relax `to` validation in base wallet subprovider for transactions that deploy contracts (#555)
-
-## v0.9.0 - _April 11, 2018_
-
- * Refactor RedundantRPCSubprovider into RedundantSubprovider where it now accepts an array of subproviders rather then an array of RPC endpoints (#500)
- * Add PrivateKeySubprovider and refactor shared functionality into a base wallet subprovider (#506)
- * Add MnemonicWalletsubprovider, deprecating our truffle-hdwallet-provider fork (#507)
- * Support multiple addresses in ledger and mnemonic wallets (#507)
- * Refactors LedgerSubprovider such that explicitly setting the `pathIndex` is no longer required. Simply set the request `from` address as desired (#507)
- * Renamed derivationPath to baseDerivationPath. (#507)
-
-## v0.8.4 - _April 2, 2018_
-
- * Dependencies updated
-
-## v0.8.3 - _April 2, 2018_
-
- * Introduce `JSONRPCRequestPayloadWithMethod` type (#465)
- * Export `ErrorCallback` type. (#465)
-
-## v0.8.0 - _March 17, 2018_
-
- * Export `GanacheSubprovider` and `Subprovider` (#426)
- * Make all subproviders to derive from `Subprovider` (#426)
- * Add types for `NextCallback`, `OnNextCompleted` (#426)
- * Ignore `ganache-core` dependency when using package in a browser environment.
-
-## v0.7.0 - _March 7, 2018_
-
- * Updated legerco packages. Removed node-hid package as a dependency and make it an optional dependency. It is still used in integration tests but is causing problems for users on Linux distros. (#437)
-
-## v0.6.0 - _March 3, 2018_
-
- * Move web3 types from being a devDep to a dep since one cannot use this package without it (#429)
- * Add `numberOfAccounts` param to `LedgerSubprovider` method `getAccountsAsync` (#432)
-
-## v0.5.0 - _February 15, 2018_
-
- * Add EmptyWalletSubprovider and FakeGasEstimateSubprovider (#392)
-
-## v0.4.1 - _February 8, 2018_
-
- * Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
-
-## v0.4.0 - _February 6, 2018_
-
- * Added NonceTrackerSubprovider (#355)
- * InjectedWeb3Subprovider accepts a Provider in the constructor, previously it was a Web3 object (#363)
-
-## v0.3.6 - _January 27, 2018_
-
- * Return a transaction hash from `_sendTransactionAsync` (#303)
-
-## v0.3.0 - _December 27, 2017_
-
- * Allow LedgerSubprovider to handle `eth_sign` in addition to `personal_sign` RPC requests
-
-## v0.2.0 - _December 19, 2017_
-
- * Improve the performance of address fetching (#271)
diff --git a/packages/subproviders/README.md b/packages/subproviders/README.md
deleted file mode 100644
index b0d77284b..000000000
--- a/packages/subproviders/README.md
+++ /dev/null
@@ -1,100 +0,0 @@
-## @0x/subproviders
-
-A few useful web3 subproviders including a LedgerSubprovider useful for adding Ledger Nano S support.
-
-We have written up a [Wiki](https://0xproject.com/wiki#Web3-Provider-Examples) article detailing some use cases of this subprovider package.
-
-### Read the [Documentation](https://0xproject.com/docs/subproviders).
-
-## Installation
-
-```
-yarn add @0x/subproviders
-```
-
-If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
-
-```json
-"compilerOptions": {
- "typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"],
-}
-```
-
-## Contributing
-
-We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
-
-Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
-
-### Install dependencies
-
-If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
-
-```bash
-yarn config set workspaces-experimental true
-```
-
-Then install dependencies
-
-```bash
-yarn install
-```
-
-### Build
-
-To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
-
-```bash
-PKG=@0x/subproviders yarn build
-```
-
-Or continuously rebuild on change:
-
-```bash
-PKG=@0x/subproviders yarn watch
-```
-
-### Clean
-
-```bash
-yarn clean
-```
-
-### Lint
-
-```bash
-yarn lint
-```
-
-### Run tests
-
-#### Unit tests
-
-```bash
-yarn run test:unit
-```
-
-#### Integration tests
-
-In order to run the integration tests, make sure you have a Ledger Nano S available.
-
-- Setup your Ledger with the development mnemonic seed: `concert load couple harbor equip island argue ramp clarify fence smart topic`
-- Plug it into your computer
-- Unlock the device
-- Open the on-device Ethereum app
-- Make sure "browser support" and "contract data" are disabled
-- Start [TestRPC](https://github.com/trufflesuite/ganache-cli) locally at port `8545`
-
-Then run:
-
-```
-yarn test:integration
-```
-
-**Note:** We assume a derivation path of `m/44'/60'/0'/0` which is already configured in the tests. With this setup and derivation path, your first account should be `0x5409ed021d9299bf6814279a6a1411a7e866a631`, exactly like TestRPC.
-
-#### All tests
-
-```bash
-yarn run test:all
-```
diff --git a/packages/subproviders/coverage/.gitkeep b/packages/subproviders/coverage/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
--- a/packages/subproviders/coverage/.gitkeep
+++ /dev/null
diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json
deleted file mode 100644
index a783bb5a2..000000000
--- a/packages/subproviders/package.json
+++ /dev/null
@@ -1,89 +0,0 @@
-{
- "name": "@0x/subproviders",
- "version": "3.0.2",
- "engines": {
- "node": ">=6.12"
- },
- "main": "lib/src/index.js",
- "types": "lib/src/index.d.ts",
- "license": "Apache-2.0",
- "scripts": {
- "build": "tsc -b",
- "build:ci": "yarn build",
- "clean": "shx rm -rf lib generated_docs",
- "lint": "tslint --format stylish --project .",
- "run_mocha_unit": "mocha --require source-map-support/register --require make-promises-safe lib/test/unit/**/*_test.js --timeout 10000 --bail --exit",
- "run_mocha_integration": "mocha --require source-map-support/register --require make-promises-safe lib/test/integration/**/*_test.js --timeout 10000 --bail --exit",
- "test": "npm run test:unit",
- "test:unit:coverage": "nyc npm run test:unit --all && yarn coverage:report:lcov",
- "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
- "test:circleci": "npm run test:unit:coverage",
- "test:all": "run-s test:unit test:integration",
- "test:unit": "run-s clean build run_mocha_unit",
- "test:integration": "run-s clean build run_mocha_integration",
- "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
- },
- "config": {
- "postpublish": {
- "assets": []
- }
- },
- "dependencies": {
- "@0x/assert": "^2.0.2",
- "@0x/types": "^2.0.2",
- "@0x/typescript-typings": "^4.0.0",
- "@0x/utils": "^4.0.3",
- "@0x/web3-wrapper": "^4.0.2",
- "@ledgerhq/hw-app-eth": "^4.3.0",
- "@ledgerhq/hw-transport-u2f": "4.24.0",
- "@types/eth-lightwallet": "^3.0.0",
- "@types/ganache-core": "^2.1.2",
- "@types/hdkey": "^0.7.0",
- "@types/web3-provider-engine": "^14.0.0",
- "bip39": "^2.5.0",
- "bn.js": "^4.11.8",
- "eth-lightwallet": "^3.0.1",
- "ethereum-types": "^2.0.0",
- "ethereumjs-tx": "^1.3.5",
- "ethereumjs-util": "^5.1.1",
- "ganache-core": "^2.3.3",
- "hdkey": "^0.7.1",
- "json-rpc-error": "2.0.0",
- "lodash": "^4.17.11",
- "semaphore-async-await": "^1.5.1",
- "web3-provider-engine": "14.0.6"
- },
- "devDependencies": {
- "@0x/tslint-config": "^3.0.0",
- "@types/bip39": "^2.4.0",
- "@types/bn.js": "^4.11.0",
- "@types/ethereumjs-tx": "^1.0.0",
- "@types/hdkey": "^0.7.0",
- "@types/lodash": "4.14.104",
- "@types/mocha": "^2.2.42",
- "@types/node": "*",
- "@types/sinon": "^2.2.2",
- "chai": "^4.0.1",
- "chai-as-promised": "^7.1.0",
- "dirty-chai": "^2.0.1",
- "make-promises-safe": "^1.1.0",
- "mocha": "^4.1.0",
- "npm-run-all": "^4.1.2",
- "nyc": "^11.0.1",
- "shx": "^0.2.2",
- "sinon": "^4.0.0",
- "tslint": "5.11.0",
- "typedoc": "0.13.0",
- "typescript": "3.0.1",
- "webpack": "^4.20.2"
- },
- "optionalDependencies": {
- "@ledgerhq/hw-transport-node-hid": "^4.3.0"
- },
- "publishConfig": {
- "access": "public"
- },
- "browser": {
- "ganache-core": false
- }
-}
diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts
deleted file mode 100644
index 3cbf84e37..000000000
--- a/packages/subproviders/src/globals.d.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-declare module '*.json' {
- const json: any;
- /* tslint:disable */
- export default json;
- /* tslint:enable */
-}
-declare module 'web3-provider-engine/util/rpc-cache-utils' {
- class ProviderEngineRpcUtils {
- public static blockTagForPayload(payload: any): string | null;
- }
- export = ProviderEngineRpcUtils;
-}
-declare module 'web3-provider-engine/subproviders/fixture' {
- import { JSONRPCRequestPayload, JSONRPCResponsePayload } from 'ethereum-types';
- class FixtureSubprovider {
- constructor(staticResponses: any);
- public handleRequest(
- payload: JSONRPCRequestPayload,
- next: () => void,
- end: (err: Error | null, data?: JSONRPCResponsePayload) => void,
- ): void;
- }
- export = FixtureSubprovider;
-}
diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts
deleted file mode 100644
index 050027f96..000000000
--- a/packages/subproviders/src/index.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import Eth from '@ledgerhq/hw-app-eth';
-import TransportU2F from '@ledgerhq/hw-transport-u2f';
-export import Web3ProviderEngine = require('web3-provider-engine');
-
-import { LedgerEthereumClient } from './types';
-
-/**
- * A factory method for creating a LedgerEthereumClient usable in a browser context.
- * @return LedgerEthereumClient A browser client for the LedgerSubprovider
- */
-export async function ledgerEthereumBrowserClientFactoryAsync(): Promise<LedgerEthereumClient> {
- const ledgerConnection = await TransportU2F.create();
- const ledgerEthClient = new Eth(ledgerConnection);
- return ledgerEthClient;
-}
-
-export { prependSubprovider } from './utils/subprovider_utils';
-
-export { EmptyWalletSubprovider } from './subproviders/empty_wallet_subprovider';
-export { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_subprovider';
-export { SignerSubprovider } from './subproviders/signer';
-export { RedundantSubprovider } from './subproviders/redundant_subprovider';
-export { LedgerSubprovider } from './subproviders/ledger';
-export { RPCSubprovider } from './subproviders/rpc_subprovider';
-export { GanacheSubprovider } from './subproviders/ganache';
-export { Subprovider } from './subproviders/subprovider';
-export { NonceTrackerSubprovider } from './subproviders/nonce_tracker';
-export { PrivateKeyWalletSubprovider } from './subproviders/private_key_wallet';
-export { MnemonicWalletSubprovider } from './subproviders/mnemonic_wallet';
-export { MetamaskSubprovider } from './subproviders/metamask_subprovider';
-export { EthLightwalletSubprovider } from './subproviders/eth_lightwallet_subprovider';
-
-export {
- Callback,
- ErrorCallback,
- NextCallback,
- LedgerCommunicationClient,
- LedgerEthereumClient,
- NonceSubproviderErrors,
- LedgerSubproviderConfigs,
- PartialTxParams,
- JSONRPCRequestPayloadWithMethod,
- ECSignatureString,
- AccountFetchingConfigs,
- LedgerEthereumClientFactoryAsync,
- OnNextCompleted,
- MnemonicWalletSubproviderConfigs,
- LedgerGetAddressResult,
-} from './types';
-
-export { ECSignature, EIP712Object, EIP712ObjectValue, EIP712TypedData, EIP712Types, EIP712Parameter } from '@0x/types';
-
-export {
- JSONRPCRequestPayload,
- Provider,
- JSONRPCResponsePayload,
- JSONRPCErrorCallback,
- JSONRPCResponseError,
-} from 'ethereum-types';
diff --git a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts b/packages/subproviders/src/subproviders/base_wallet_subprovider.ts
deleted file mode 100644
index e9d104074..000000000
--- a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-import { assert } from '@0x/assert';
-import { addressUtils } from '@0x/utils';
-import { JSONRPCRequestPayload, JSONRPCResponsePayload } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { Callback, ErrorCallback, PartialTxParams, WalletSubproviderErrors } from '../types';
-
-import { Subprovider } from './subprovider';
-
-export abstract class BaseWalletSubprovider extends Subprovider {
- protected static _validateTxParams(txParams: PartialTxParams): void {
- if (!_.isUndefined(txParams.to)) {
- assert.isETHAddressHex('to', txParams.to);
- }
- assert.isHexString('nonce', txParams.nonce);
- }
- private static _validateSender(sender: string): void {
- if (_.isUndefined(sender) || !addressUtils.isAddress(sender)) {
- throw new Error(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
- }
- }
-
- public abstract async getAccountsAsync(): Promise<string[]>;
- public abstract async signTransactionAsync(txParams: PartialTxParams): Promise<string>;
- public abstract async signPersonalMessageAsync(data: string, address: string): Promise<string>;
- public abstract async signTypedDataAsync(address: string, typedData: any): Promise<string>;
-
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- let accounts;
- let txParams;
- let address;
- let typedData;
- switch (payload.method) {
- case 'eth_coinbase':
- try {
- accounts = await this.getAccountsAsync();
- end(null, accounts[0]);
- } catch (err) {
- end(err);
- }
- return;
-
- case 'eth_accounts':
- try {
- accounts = await this.getAccountsAsync();
- end(null, accounts);
- } catch (err) {
- end(err);
- }
- return;
-
- case 'eth_sendTransaction':
- txParams = payload.params[0];
- try {
- BaseWalletSubprovider._validateSender(txParams.from);
- const filledParams = await this._populateMissingTxParamsAsync(txParams);
- const signedTx = await this.signTransactionAsync(filledParams);
- const response = await this._emitSendTransactionAsync(signedTx);
- end(null, response.result);
- } catch (err) {
- end(err);
- }
- return;
-
- case 'eth_signTransaction':
- txParams = payload.params[0];
- try {
- const filledParams = await this._populateMissingTxParamsAsync(txParams);
- const signedTx = await this.signTransactionAsync(filledParams);
- const result = {
- raw: signedTx,
- tx: txParams,
- };
- end(null, result);
- } catch (err) {
- end(err);
- }
- return;
-
- case 'eth_sign':
- case 'personal_sign':
- const data = payload.method === 'eth_sign' ? payload.params[1] : payload.params[0];
- address = payload.method === 'eth_sign' ? payload.params[0] : payload.params[1];
- try {
- const ecSignatureHex = await this.signPersonalMessageAsync(data, address);
- end(null, ecSignatureHex);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_signTypedData':
- [address, typedData] = payload.params;
- try {
- const signature = await this.signTypedDataAsync(address, typedData);
- end(null, signature);
- } catch (err) {
- end(err);
- }
- return;
-
- default:
- next();
- return;
- }
- }
- private async _emitSendTransactionAsync(signedTx: string): Promise<JSONRPCResponsePayload> {
- const payload = {
- method: 'eth_sendRawTransaction',
- params: [signedTx],
- };
- const result = await this.emitPayloadAsync(payload);
- return result;
- }
- private async _populateMissingTxParamsAsync(partialTxParams: PartialTxParams): Promise<PartialTxParams> {
- let txParams = partialTxParams;
- if (_.isUndefined(partialTxParams.gasPrice)) {
- const gasPriceResult = await this.emitPayloadAsync({
- method: 'eth_gasPrice',
- params: [],
- });
- const gasPrice = gasPriceResult.result.toString();
- txParams = { ...txParams, gasPrice };
- }
- if (_.isUndefined(partialTxParams.nonce)) {
- const nonceResult = await this.emitPayloadAsync({
- method: 'eth_getTransactionCount',
- params: [partialTxParams.from, 'pending'],
- });
- const nonce = nonceResult.result;
- txParams = { ...txParams, nonce };
- }
- if (_.isUndefined(partialTxParams.gas)) {
- const gasResult = await this.emitPayloadAsync({
- method: 'eth_estimateGas',
- params: [partialTxParams],
- });
- const gas = gasResult.result.toString();
- txParams = { ...txParams, gas };
- }
- return txParams;
- }
-}
diff --git a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
deleted file mode 100644
index 4268c67bd..000000000
--- a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { JSONRPCRequestPayload } from 'ethereum-types';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It intercepts the `eth_accounts` JSON RPC requests and never returns any addresses when queried.
- */
-export class EmptyWalletSubprovider extends Subprovider {
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:prefer-function-over-method async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- switch (payload.method) {
- case 'eth_accounts':
- end(null, []);
- return;
-
- default:
- next();
- return;
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
deleted file mode 100644
index 15cd713af..000000000
--- a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import { EIP712TypedData } from '@0x/types';
-import * as lightwallet from 'eth-lightwallet';
-
-import { PartialTxParams } from '../types';
-
-import { BaseWalletSubprovider } from './base_wallet_subprovider';
-import { PrivateKeyWalletSubprovider } from './private_key_wallet';
-
-/*
- * This class implements the web3-provider-engine subprovider interface and forwards
- * requests involving user accounts and signing operations to eth-lightwallet
- *
- * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
- */
-export class EthLightwalletSubprovider extends BaseWalletSubprovider {
- private readonly _keystore: lightwallet.keystore;
- private readonly _pwDerivedKey: Uint8Array;
- /**
- * Instantiate an EthLightwalletSubprovider
- * @param keystore The EthLightWallet keystore you wish to use
- * @param pwDerivedKey The password derived key to use
- * @return EthLightwalletSubprovider instance
- */
- constructor(keystore: lightwallet.keystore, pwDerivedKey: Uint8Array) {
- super();
- this._keystore = keystore;
- this._pwDerivedKey = pwDerivedKey;
- }
- /**
- * Retrieve the accounts associated with the eth-lightwallet instance.
- * This method is implicitly called when issuing a `eth_accounts` JSON RPC request
- * via your providerEngine instance.
- *
- * @return An array of accounts
- */
- public async getAccountsAsync(): Promise<string[]> {
- const accounts = this._keystore.getAddresses();
- return accounts;
- }
- /**
- * Signs a transaction with the account specificed by the `from` field in txParams.
- * If you've added this Subprovider to your app's provider, you can simply send
- * an `eth_sendTransaction` JSON RPC request, and this method will be called auto-magically.
- * If you are not using this via a ProviderEngine instance, you can call it directly.
- * @param txParams Parameters of the transaction to sign
- * @return Signed transaction hex string
- */
- public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
- // Lightwallet loses the chain id information when hex encoding the transaction
- // this results in a different signature on certain networks. PrivateKeyWallet
- // respects this as it uses the parameters passed in
- let privateKey = this._keystore.exportPrivateKey(txParams.from, this._pwDerivedKey);
- const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
- privateKey = '';
- const privateKeySignature = await privateKeyWallet.signTransactionAsync(txParams);
- return privateKeySignature;
- }
- /**
- * Sign a personal Ethereum signed message. The signing account will be the account
- * associated with the provided address.
- * If you've added this Subprovider to your app's provider, you can simply send an `eth_sign`
- * or `personal_sign` JSON RPC request, and this method will be called auto-magically.
- * If you are not using this via a ProviderEngine instance, you can call it directly.
- * @param data Hex string message to sign
- * @param address Address of the account to sign with
- * @return Signature hex string (order: rsv)
- */
- public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- let privateKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey);
- const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
- privateKey = '';
- const result = privateKeyWallet.signPersonalMessageAsync(data, address);
- return result;
- }
- /**
- * Sign an EIP712 Typed Data message. The signing address will associated with the provided address.
- * If you've added this Subprovider to your app's provider, you can simply send an `eth_signTypedData`
- * JSON RPC request, and this method will be called auto-magically.
- * If you are not using this via a ProviderEngine instance, you can call it directly.
- * @param address Address of the account to sign with
- * @param data the typed data object
- * @return Signature hex string (order: rsv)
- */
- public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
- let privateKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey);
- const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
- privateKey = '';
- const result = privateKeyWallet.signTypedDataAsync(address, typedData);
- return result;
- }
-}
diff --git a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
deleted file mode 100644
index bc1b34aba..000000000
--- a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { JSONRPCRequestPayload } from 'ethereum-types';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-// HACK: We need this so that our tests don't use testrpc gas estimation which sometimes kills the node.
-// Source: https://github.com/trufflesuite/ganache-cli/issues/417
-// Source: https://github.com/trufflesuite/ganache-cli/issues/437
-// Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It intercepts the `eth_estimateGas` JSON RPC call and always returns a constant gas amount when queried.
- */
-export class FakeGasEstimateSubprovider extends Subprovider {
- private readonly _constantGasAmount: number;
- /**
- * Instantiates an instance of the FakeGasEstimateSubprovider
- * @param constantGasAmount The constant gas amount you want returned
- */
- constructor(constantGasAmount: number) {
- super();
- this._constantGasAmount = constantGasAmount;
- }
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:prefer-function-over-method async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- switch (payload.method) {
- case 'eth_estimateGas':
- end(null, this._constantGasAmount);
- return;
-
- default:
- next();
- return;
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts
deleted file mode 100644
index 2b8544f8b..000000000
--- a/packages/subproviders/src/subproviders/ganache.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { JSONRPCRequestPayload, Provider } from 'ethereum-types';
-import * as Ganache from 'ganache-core';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It intercepts all JSON RPC requests and relays them to an in-process ganache instance.
- */
-export class GanacheSubprovider extends Subprovider {
- private readonly _ganacheProvider: Provider;
- /**
- * Instantiates a GanacheSubprovider
- * @param opts The desired opts with which to instantiate the Ganache provider
- */
- constructor(opts: Ganache.GanacheOpts) {
- super();
- this._ganacheProvider = Ganache.provider(opts);
- }
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param _next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:prefer-function-over-method async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, _next: Callback, end: ErrorCallback): Promise<void> {
- this._ganacheProvider.sendAsync(payload, (err: Error | null, result: any) => {
- end(err, result && result.result);
- });
- }
-}
diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts
deleted file mode 100644
index b5ca10ce1..000000000
--- a/packages/subproviders/src/subproviders/ledger.ts
+++ /dev/null
@@ -1,256 +0,0 @@
-import { assert } from '@0x/assert';
-import { addressUtils } from '@0x/utils';
-import EthereumTx = require('ethereumjs-tx');
-import ethUtil = require('ethereumjs-util');
-import HDNode = require('hdkey');
-import * as _ from 'lodash';
-import { Lock } from 'semaphore-async-await';
-
-import {
- DerivedHDKeyInfo,
- LedgerEthereumClient,
- LedgerEthereumClientFactoryAsync,
- LedgerSubproviderConfigs,
- LedgerSubproviderErrors,
- PartialTxParams,
- WalletSubproviderErrors,
-} from '../types';
-import { walletUtils } from '../utils/wallet_utils';
-
-import { BaseWalletSubprovider } from './base_wallet_subprovider';
-
-const DEFAULT_BASE_DERIVATION_PATH = `44'/60'/0'`;
-const ASK_FOR_ON_DEVICE_CONFIRMATION = false;
-const SHOULD_GET_CHAIN_CODE = true;
-const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10;
-const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000;
-
-/**
- * Subprovider for interfacing with a user's [Ledger Nano S](https://www.ledgerwallet.com/products/ledger-nano-s).
- * This subprovider intercepts all account related RPC requests (e.g message/transaction signing, etc...) and
- * re-routes them to a Ledger device plugged into the users computer.
- */
-export class LedgerSubprovider extends BaseWalletSubprovider {
- // tslint:disable-next-line:no-unused-variable
- private readonly _connectionLock = new Lock();
- private readonly _networkId: number;
- private _baseDerivationPath: string;
- private readonly _ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync;
- private _ledgerClientIfExists?: LedgerEthereumClient;
- private readonly _shouldAlwaysAskForConfirmation: boolean;
- private readonly _addressSearchLimit: number;
- /**
- * Instantiates a LedgerSubprovider. Defaults to derivationPath set to `44'/60'/0'`.
- * TestRPC/Ganache defaults to `m/44'/60'/0'/0`, so set this in the configs if desired.
- * @param config Several available configurations
- * @return LedgerSubprovider instance
- */
- constructor(config: LedgerSubproviderConfigs) {
- super();
- this._networkId = config.networkId;
- this._ledgerEthereumClientFactoryAsync = config.ledgerEthereumClientFactoryAsync;
- this._baseDerivationPath = config.baseDerivationPath || DEFAULT_BASE_DERIVATION_PATH;
- this._shouldAlwaysAskForConfirmation =
- !_.isUndefined(config.accountFetchingConfigs) &&
- !_.isUndefined(config.accountFetchingConfigs.shouldAskForOnDeviceConfirmation)
- ? config.accountFetchingConfigs.shouldAskForOnDeviceConfirmation
- : ASK_FOR_ON_DEVICE_CONFIRMATION;
- this._addressSearchLimit =
- !_.isUndefined(config.accountFetchingConfigs) &&
- !_.isUndefined(config.accountFetchingConfigs.addressSearchLimit)
- ? config.accountFetchingConfigs.addressSearchLimit
- : DEFAULT_ADDRESS_SEARCH_LIMIT;
- }
- /**
- * Retrieve the set derivation path
- * @returns derivation path
- */
- public getPath(): string {
- return this._baseDerivationPath;
- }
- /**
- * Set a desired derivation path when computing the available user addresses
- * @param basDerivationPath The desired derivation path (e.g `44'/60'/0'`)
- */
- public setPath(basDerivationPath: string): void {
- this._baseDerivationPath = basDerivationPath;
- }
- /**
- * Retrieve a users Ledger accounts. The accounts are derived from the derivationPath,
- * master public key and chain code. Because of this, you can request as many accounts
- * as you wish and it only requires a single request to the Ledger device. This method
- * is automatically called when issuing a `eth_accounts` JSON RPC request via your providerEngine
- * instance.
- * @param numberOfAccounts Number of accounts to retrieve (default: 10)
- * @return An array of accounts
- */
- public async getAccountsAsync(numberOfAccounts: number = DEFAULT_NUM_ADDRESSES_TO_FETCH): Promise<string[]> {
- const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync();
- const derivedKeyInfos = walletUtils.calculateDerivedHDKeyInfos(initialDerivedKeyInfo, numberOfAccounts);
- const accounts = _.map(derivedKeyInfos, k => k.address);
- return accounts;
- }
- /**
- * Signs a transaction on the Ledger with the account specificed by the `from` field in txParams.
- * If you've added the LedgerSubprovider to your app's provider, you can simply send an `eth_sendTransaction`
- * JSON RPC request, and this method will be called auto-magically. If you are not using this via a ProviderEngine
- * instance, you can call it directly.
- * @param txParams Parameters of the transaction to sign
- * @return Signed transaction hex string
- */
- public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
- LedgerSubprovider._validateTxParams(txParams);
- if (_.isUndefined(txParams.from) || !addressUtils.isAddress(txParams.from)) {
- throw new Error(WalletSubproviderErrors.FromAddressMissingOrInvalid);
- }
- const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync();
- const derivedKeyInfo = this._findDerivedKeyInfoForAddress(initialDerivedKeyInfo, txParams.from);
-
- this._ledgerClientIfExists = await this._createLedgerClientAsync();
-
- const tx = new EthereumTx(txParams);
-
- // Set the EIP155 bits
- const vIndex = 6;
- tx.raw[vIndex] = Buffer.from([this._networkId]); // v
- const rIndex = 7;
- tx.raw[rIndex] = Buffer.from([]); // r
- const sIndex = 8;
- tx.raw[sIndex] = Buffer.from([]); // s
-
- const txHex = tx.serialize().toString('hex');
- try {
- const fullDerivationPath = derivedKeyInfo.derivationPath;
- const result = await this._ledgerClientIfExists.signTransaction(fullDerivationPath, txHex);
- // Store signature in transaction
- tx.r = Buffer.from(result.r, 'hex');
- tx.s = Buffer.from(result.s, 'hex');
- tx.v = Buffer.from(result.v, 'hex');
-
- // EIP155: v should be chain_id * 2 + {35, 36}
- const eip55Constant = 35;
- const signedChainId = Math.floor((tx.v[0] - eip55Constant) / 2);
- if (signedChainId !== this._networkId) {
- await this._destroyLedgerClientAsync();
- const err = new Error(LedgerSubproviderErrors.TooOldLedgerFirmware);
- throw err;
- }
-
- const signedTxHex = `0x${tx.serialize().toString('hex')}`;
- await this._destroyLedgerClientAsync();
- return signedTxHex;
- } catch (err) {
- await this._destroyLedgerClientAsync();
- throw err;
- }
- }
- /**
- * Sign a personal Ethereum signed message. The signing account will be the account
- * associated with the provided address.
- * The Ledger adds the Ethereum signed message prefix on-device. If you've added
- * the LedgerSubprovider to your app's provider, you can simply send an `eth_sign`
- * or `personal_sign` JSON RPC request, and this method will be called auto-magically.
- * If you are not using this via a ProviderEngine instance, you can call it directly.
- * @param data Hex string message to sign
- * @param address Address of the account to sign with
- * @return Signature hex string (order: rsv)
- */
- public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- if (_.isUndefined(data)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isHexString('data', data);
- assert.isETHAddressHex('address', address);
- const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync();
- const derivedKeyInfo = this._findDerivedKeyInfoForAddress(initialDerivedKeyInfo, address);
-
- this._ledgerClientIfExists = await this._createLedgerClientAsync();
- try {
- const fullDerivationPath = derivedKeyInfo.derivationPath;
- const result = await this._ledgerClientIfExists.signPersonalMessage(
- fullDerivationPath,
- ethUtil.stripHexPrefix(data),
- );
- const lowestValidV = 27;
- const v = result.v - lowestValidV;
- const hexBase = 16;
- let vHex = v.toString(hexBase);
- if (vHex.length < 2) {
- vHex = `0${v}`;
- }
- const signature = `0x${result.r}${result.s}${vHex}`;
- await this._destroyLedgerClientAsync();
- return signature;
- } catch (err) {
- await this._destroyLedgerClientAsync();
- throw err;
- }
- }
- /**
- * eth_signTypedData is currently not supported on Ledger devices.
- * @param address Address of the account to sign with
- * @param data the typed data object
- * @return Signature hex string (order: rsv)
- */
- // tslint:disable-next-line:prefer-function-over-method
- public async signTypedDataAsync(address: string, typedData: any): Promise<string> {
- throw new Error(WalletSubproviderErrors.MethodNotSupported);
- }
- private async _createLedgerClientAsync(): Promise<LedgerEthereumClient> {
- await this._connectionLock.acquire();
- if (!_.isUndefined(this._ledgerClientIfExists)) {
- this._connectionLock.release();
- throw new Error(LedgerSubproviderErrors.MultipleOpenConnectionsDisallowed);
- }
- const ledgerEthereumClient = await this._ledgerEthereumClientFactoryAsync();
- this._connectionLock.release();
- return ledgerEthereumClient;
- }
- private async _destroyLedgerClientAsync(): Promise<void> {
- await this._connectionLock.acquire();
- if (_.isUndefined(this._ledgerClientIfExists)) {
- this._connectionLock.release();
- return;
- }
- await this._ledgerClientIfExists.transport.close();
- this._ledgerClientIfExists = undefined;
- this._connectionLock.release();
- }
- private async _initialDerivedKeyInfoAsync(): Promise<DerivedHDKeyInfo> {
- this._ledgerClientIfExists = await this._createLedgerClientAsync();
-
- const parentKeyDerivationPath = `m/${this._baseDerivationPath}`;
- let ledgerResponse;
- try {
- ledgerResponse = await this._ledgerClientIfExists.getAddress(
- parentKeyDerivationPath,
- this._shouldAlwaysAskForConfirmation,
- SHOULD_GET_CHAIN_CODE,
- );
- } finally {
- await this._destroyLedgerClientAsync();
- }
- const hdKey = new HDNode();
- hdKey.publicKey = new Buffer(ledgerResponse.publicKey, 'hex');
- hdKey.chainCode = new Buffer(ledgerResponse.chainCode, 'hex');
- const address = walletUtils.addressOfHDKey(hdKey);
- const initialDerivedKeyInfo = {
- hdKey,
- address,
- derivationPath: parentKeyDerivationPath,
- baseDerivationPath: this._baseDerivationPath,
- };
- return initialDerivedKeyInfo;
- }
- private _findDerivedKeyInfoForAddress(initalHDKey: DerivedHDKeyInfo, address: string): DerivedHDKeyInfo {
- const matchedDerivedKeyInfo = walletUtils.findDerivedKeyInfoForAddressIfExists(
- address,
- initalHDKey,
- this._addressSearchLimit,
- );
- if (_.isUndefined(matchedDerivedKeyInfo)) {
- throw new Error(`${WalletSubproviderErrors.AddressNotFound}: ${address}`);
- }
- return matchedDerivedKeyInfo;
- }
-}
diff --git a/packages/subproviders/src/subproviders/metamask_subprovider.ts b/packages/subproviders/src/subproviders/metamask_subprovider.ts
deleted file mode 100644
index ba207d4cc..000000000
--- a/packages/subproviders/src/subproviders/metamask_subprovider.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-import { marshaller, Web3Wrapper } from '@0x/web3-wrapper';
-import { JSONRPCRequestPayload, Provider } from 'ethereum-types';
-import * as ethUtil from 'ethereumjs-util';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine)
- * subprovider interface and the provider sendAsync interface.
- * It handles inconsistencies with Metamask implementations of various JSON RPC methods.
- * It forwards JSON RPC requests involving the domain of a signer (getAccounts,
- * sendTransaction, signMessage etc...) to the provider instance supplied at instantiation. All other requests
- * are passed onwards for subsequent subproviders to handle.
- */
-export class MetamaskSubprovider extends Subprovider {
- private readonly _web3Wrapper: Web3Wrapper;
- private readonly _provider: Provider;
- /**
- * Instantiates a new MetamaskSubprovider
- * @param provider Web3 provider that should handle all user account related requests
- */
- constructor(provider: Provider) {
- super();
- this._web3Wrapper = new Web3Wrapper(provider);
- this._provider = provider;
- }
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:prefer-function-over-method async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- let message;
- let address;
- switch (payload.method) {
- case 'web3_clientVersion':
- try {
- const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
- end(null, nodeVersion);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_accounts':
- try {
- const accounts = await this._web3Wrapper.getAvailableAddressesAsync();
- end(null, accounts);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_sendTransaction':
- const [txParams] = payload.params;
- try {
- const txData = marshaller.unmarshalTxData(txParams);
- const txHash = await this._web3Wrapper.sendTransactionAsync(txData);
- end(null, txHash);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_sign':
- [address, message] = payload.params;
- try {
- // Metamask incorrectly implements eth_sign and does not prefix the message as per the spec
- // Source: https://github.com/MetaMask/metamask-extension/commit/a9d36860bec424dcee8db043d3e7da6a5ff5672e
- const msgBuff = ethUtil.toBuffer(message);
- const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff);
- const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
- const signature = await this._web3Wrapper.signMessageAsync(address, prefixedMsgHex);
- signature ? end(null, signature) : end(new Error('Error performing eth_sign'), null);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_signTypedData':
- case 'eth_signTypedData_v3':
- [address, message] = payload.params;
- try {
- // Metamask supports multiple versions and has namespaced signTypedData to v3 for an indeterminate period of time.
- // eth_signTypedData is mapped to an older implementation before the spec was finalized.
- // Source: https://github.com/MetaMask/metamask-extension/blob/c49d854b55b3efd34c7fd0414b76f7feaa2eec7c/app/scripts/metamask-controller.js#L1262
- // and expects message to be serialised as JSON
- const messageJSON = JSON.stringify(message);
- const signature = await this._web3Wrapper.sendRawPayloadAsync<string>({
- method: 'eth_signTypedData_v3',
- params: [address, messageJSON],
- });
- signature ? end(null, signature) : end(new Error('Error performing eth_signTypedData'), null);
- } catch (err) {
- end(err);
- }
- return;
- default:
- next();
- return;
- }
- }
- /**
- * This method conforms to the provider sendAsync interface.
- * Allowing the MetamaskSubprovider to be used as a generic provider (outside of Web3ProviderEngine) with the
- * addition of wrapping the inconsistent Metamask behaviour
- * @param payload JSON RPC payload
- * @return The contents nested under the result key of the response body
- */
- public sendAsync(payload: JSONRPCRequestPayload, callback: ErrorCallback): void {
- void this.handleRequest(
- payload,
- // handleRequest has decided to not handle this, so fall through to the provider
- () => {
- const sendAsync = this._provider.sendAsync.bind(this._provider);
- sendAsync(payload, callback);
- },
- // handleRequest has called end and will handle this
- (err, data) => {
- err ? callback(err) : callback(null, { ...payload, result: data });
- },
- );
- }
-}
diff --git a/packages/subproviders/src/subproviders/mnemonic_wallet.ts b/packages/subproviders/src/subproviders/mnemonic_wallet.ts
deleted file mode 100644
index 140e3d515..000000000
--- a/packages/subproviders/src/subproviders/mnemonic_wallet.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-import { assert } from '@0x/assert';
-import { EIP712TypedData } from '@0x/types';
-import { addressUtils } from '@0x/utils';
-import * as bip39 from 'bip39';
-import HDNode = require('hdkey');
-import * as _ from 'lodash';
-
-import { DerivedHDKeyInfo, MnemonicWalletSubproviderConfigs, PartialTxParams, WalletSubproviderErrors } from '../types';
-import { walletUtils } from '../utils/wallet_utils';
-
-import { BaseWalletSubprovider } from './base_wallet_subprovider';
-import { PrivateKeyWalletSubprovider } from './private_key_wallet';
-
-const DEFAULT_BASE_DERIVATION_PATH = `44'/60'/0'/0`;
-const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10;
-const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000;
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * This subprovider intercepts all account related RPC requests (e.g message/transaction signing, etc...) and handles
- * all requests with accounts derived from the supplied mnemonic.
- */
-export class MnemonicWalletSubprovider extends BaseWalletSubprovider {
- private readonly _addressSearchLimit: number;
- private _baseDerivationPath: string;
- private _derivedKeyInfo: DerivedHDKeyInfo;
- private readonly _mnemonic: string;
-
- /**
- * Instantiates a MnemonicWalletSubprovider. Defaults to baseDerivationPath set to `44'/60'/0'/0`.
- * This is the default in TestRPC/Ganache, it can be overridden if desired.
- * @param config Configuration for the mnemonic wallet, must contain the mnemonic
- * @return MnemonicWalletSubprovider instance
- */
- constructor(config: MnemonicWalletSubproviderConfigs) {
- assert.isString('mnemonic', config.mnemonic);
- const baseDerivationPath = config.baseDerivationPath || DEFAULT_BASE_DERIVATION_PATH;
- assert.isString('baseDerivationPath', baseDerivationPath);
- const addressSearchLimit = config.addressSearchLimit || DEFAULT_ADDRESS_SEARCH_LIMIT;
- assert.isNumber('addressSearchLimit', addressSearchLimit);
- super();
-
- this._mnemonic = config.mnemonic;
- this._baseDerivationPath = baseDerivationPath;
- this._addressSearchLimit = addressSearchLimit;
- this._derivedKeyInfo = this._initialDerivedKeyInfo(this._baseDerivationPath);
- }
- /**
- * Retrieve the set derivation path
- * @returns derivation path
- */
- public getPath(): string {
- return this._baseDerivationPath;
- }
- /**
- * Set a desired derivation path when computing the available user addresses
- * @param baseDerivationPath The desired derivation path (e.g `44'/60'/0'`)
- */
- public setPath(baseDerivationPath: string): void {
- this._baseDerivationPath = baseDerivationPath;
- this._derivedKeyInfo = this._initialDerivedKeyInfo(this._baseDerivationPath);
- }
- /**
- * Retrieve the accounts associated with the mnemonic.
- * This method is implicitly called when issuing a `eth_accounts` JSON RPC request
- * via your providerEngine instance.
- * @param numberOfAccounts Number of accounts to retrieve (default: 10)
- * @return An array of accounts
- */
- public async getAccountsAsync(numberOfAccounts: number = DEFAULT_NUM_ADDRESSES_TO_FETCH): Promise<string[]> {
- const derivedKeys = walletUtils.calculateDerivedHDKeyInfos(this._derivedKeyInfo, numberOfAccounts);
- const accounts = _.map(derivedKeys, k => k.address);
- return accounts;
- }
-
- /**
- * Signs a transaction with the account specificed by the `from` field in txParams.
- * If you've added this Subprovider to your app's provider, you can simply send
- * an `eth_sendTransaction` JSON RPC request, and this method will be called auto-magically.
- * If you are not using this via a ProviderEngine instance, you can call it directly.
- * @param txParams Parameters of the transaction to sign
- * @return Signed transaction hex string
- */
- public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
- if (_.isUndefined(txParams.from) || !addressUtils.isAddress(txParams.from)) {
- throw new Error(WalletSubproviderErrors.FromAddressMissingOrInvalid);
- }
- const privateKeyWallet = this._privateKeyWalletForAddress(txParams.from);
- const signedTx = privateKeyWallet.signTransactionAsync(txParams);
- return signedTx;
- }
- /**
- * Sign a personal Ethereum signed message. The signing account will be the account
- * associated with the provided address. If you've added the MnemonicWalletSubprovider to
- * your app's provider, you can simply send an `eth_sign` or `personal_sign` JSON RPC request,
- * and this method will be called auto-magically. If you are not using this via a ProviderEngine
- * instance, you can call it directly.
- * @param data Hex string message to sign
- * @param address Address of the account to sign with
- * @return Signature hex string (order: rsv)
- */
- public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- if (_.isUndefined(data)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isHexString('data', data);
- assert.isETHAddressHex('address', address);
- const privateKeyWallet = this._privateKeyWalletForAddress(address);
- const sig = await privateKeyWallet.signPersonalMessageAsync(data, address);
- return sig;
- }
- /**
- * Sign an EIP712 Typed Data message. The signing account will be the account
- * associated with the provided address. If you've added this MnemonicWalletSubprovider to
- * your app's provider, you can simply send an `eth_signTypedData` JSON RPC request, and
- * this method will be called auto-magically. If you are not using this via a ProviderEngine
- * instance, you can call it directly.
- * @param address Address of the account to sign with
- * @param data the typed data object
- * @return Signature hex string (order: rsv)
- */
- public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
- if (_.isUndefined(typedData)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isETHAddressHex('address', address);
- const privateKeyWallet = this._privateKeyWalletForAddress(address);
- const sig = await privateKeyWallet.signTypedDataAsync(address, typedData);
- return sig;
- }
- private _privateKeyWalletForAddress(address: string): PrivateKeyWalletSubprovider {
- const derivedKeyInfo = this._findDerivedKeyInfoForAddress(address);
- const privateKeyHex = derivedKeyInfo.hdKey.privateKey.toString('hex');
- const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKeyHex);
- return privateKeyWallet;
- }
- private _findDerivedKeyInfoForAddress(address: string): DerivedHDKeyInfo {
- const matchedDerivedKeyInfo = walletUtils.findDerivedKeyInfoForAddressIfExists(
- address,
- this._derivedKeyInfo,
- this._addressSearchLimit,
- );
- if (_.isUndefined(matchedDerivedKeyInfo)) {
- throw new Error(`${WalletSubproviderErrors.AddressNotFound}: ${address}`);
- }
- return matchedDerivedKeyInfo;
- }
- private _initialDerivedKeyInfo(baseDerivationPath: string): DerivedHDKeyInfo {
- const seed = bip39.mnemonicToSeed(this._mnemonic);
- const hdKey = HDNode.fromMasterSeed(seed);
- // Walk down to base derivation level (i.e m/44'/60'/0') and create an initial key at that level
- // all children will then be walked relative (i.e m/0)
- const parentKeyDerivationPath = `m/${baseDerivationPath}`;
- const parentHDKeyAtDerivationPath = hdKey.derive(parentKeyDerivationPath);
- const address = walletUtils.addressOfHDKey(parentHDKeyAtDerivationPath);
- const derivedKeyInfo = {
- address,
- baseDerivationPath,
- derivationPath: parentKeyDerivationPath,
- hdKey: parentHDKeyAtDerivationPath,
- };
- return derivedKeyInfo;
- }
-}
diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts
deleted file mode 100644
index eea722aee..000000000
--- a/packages/subproviders/src/subproviders/nonce_tracker.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-import * as _ from 'lodash';
-
-import { BlockParamLiteral, JSONRPCRequestPayload } from 'ethereum-types';
-import EthereumTx = require('ethereumjs-tx');
-import ethUtil = require('ethereumjs-util');
-import providerEngineUtils = require('web3-provider-engine/util/rpc-cache-utils');
-
-import { Callback, ErrorCallback, NextCallback, NonceSubproviderErrors } from '../types';
-
-import { Subprovider } from './subprovider';
-
-const NONCE_TOO_LOW_ERROR_MESSAGE = 'Transaction nonce is too low';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It is heavily inspired by the [NonceSubprovider](https://github.com/MetaMask/provider-engine/blob/master/subproviders/nonce-tracker.js).
- * We added the additional feature of clearing the cached nonce value when a `nonce value too low` error occurs.
- */
-export class NonceTrackerSubprovider extends Subprovider {
- private readonly _nonceCache: { [address: string]: string } = {};
- private static _reconstructTransaction(payload: JSONRPCRequestPayload): EthereumTx {
- const raw = payload.params[0];
- if (_.isUndefined(raw)) {
- throw new Error(NonceSubproviderErrors.EmptyParametersFound);
- }
- const rawData = ethUtil.toBuffer(raw);
- const transaction = new EthereumTx(rawData);
- return transaction;
- }
- private static _determineAddress(payload: JSONRPCRequestPayload): string {
- let address: string;
- switch (payload.method) {
- case 'eth_getTransactionCount':
- address = payload.params[0].toLowerCase();
- return address;
- case 'eth_sendRawTransaction':
- const transaction = NonceTrackerSubprovider._reconstructTransaction(payload);
- const addressRaw = transaction
- .getSenderAddress()
- .toString('hex')
- .toLowerCase();
- address = `0x${addressRaw}`;
- return address;
- default:
- throw new Error(NonceSubproviderErrors.CannotDetermineAddressFromPayload);
- }
- }
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: NextCallback, end: ErrorCallback): Promise<void> {
- switch (payload.method) {
- case 'eth_getTransactionCount':
- const requestDefaultBlock = providerEngineUtils.blockTagForPayload(payload);
- if (requestDefaultBlock === BlockParamLiteral.Pending) {
- const address = NonceTrackerSubprovider._determineAddress(payload);
- const cachedResult = this._nonceCache[address];
- if (!_.isUndefined(cachedResult)) {
- return end(null, cachedResult);
- } else {
- return next((requestError: Error | null, requestResult: any, cb: Callback) => {
- if (_.isNull(requestError)) {
- this._nonceCache[address] = requestResult as string;
- }
- cb();
- });
- }
- } else {
- return next();
- }
- case 'eth_sendRawTransaction':
- return next((sendTransactionError: Error | null, _txResult: any, cb: Callback) => {
- if (_.isNull(sendTransactionError)) {
- this._handleSuccessfulTransaction(payload);
- } else {
- this._handleSendTransactionError(payload, sendTransactionError);
- }
- cb();
- });
- default:
- return next();
- }
- }
- private _handleSuccessfulTransaction(payload: JSONRPCRequestPayload): void {
- const address = NonceTrackerSubprovider._determineAddress(payload);
- const transaction = NonceTrackerSubprovider._reconstructTransaction(payload);
- // Increment the nonce from the previous successfully submitted transaction
- let nonce = ethUtil.bufferToInt(transaction.nonce);
- nonce++;
- const hexBase = 16;
- let nextHexNonce = nonce.toString(hexBase);
- if (nextHexNonce.length % 2) {
- nextHexNonce = `0${nextHexNonce}`;
- }
- const nextPrefixedHexNonce = `0x${nextHexNonce}`;
- this._nonceCache[address] = nextPrefixedHexNonce;
- }
- private _handleSendTransactionError(payload: JSONRPCRequestPayload, err: Error): void {
- const address = NonceTrackerSubprovider._determineAddress(payload);
- if (this._nonceCache[address] && _.includes(err.message, NONCE_TOO_LOW_ERROR_MESSAGE)) {
- delete this._nonceCache[address];
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/private_key_wallet.ts b/packages/subproviders/src/subproviders/private_key_wallet.ts
deleted file mode 100644
index dca7e6810..000000000
--- a/packages/subproviders/src/subproviders/private_key_wallet.ts
+++ /dev/null
@@ -1,114 +0,0 @@
-import { assert } from '@0x/assert';
-import { EIP712TypedData } from '@0x/types';
-import { signTypedDataUtils } from '@0x/utils';
-import EthereumTx = require('ethereumjs-tx');
-import * as ethUtil from 'ethereumjs-util';
-import * as _ from 'lodash';
-
-import { PartialTxParams, WalletSubproviderErrors } from '../types';
-
-import { BaseWalletSubprovider } from './base_wallet_subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * This subprovider intercepts all account related RPC requests (e.g message/transaction signing, etc...) and handles
- * all requests with the supplied Ethereum private key.
- */
-export class PrivateKeyWalletSubprovider extends BaseWalletSubprovider {
- private readonly _address: string;
- private readonly _privateKeyBuffer: Buffer;
- /**
- * Instantiates a PrivateKeyWalletSubprovider.
- * @param privateKey The corresponding private key to an Ethereum address
- * @return PrivateKeyWalletSubprovider instance
- */
- constructor(privateKey: string) {
- assert.isString('privateKey', privateKey);
- super();
- this._privateKeyBuffer = Buffer.from(privateKey, 'hex');
- this._address = `0x${ethUtil.privateToAddress(this._privateKeyBuffer).toString('hex')}`;
- }
- /**
- * Retrieve the account associated with the supplied private key.
- * This method is implicitly called when issuing a `eth_accounts` JSON RPC request
- * via your providerEngine instance.
- * @return An array of accounts
- */
- public async getAccountsAsync(): Promise<string[]> {
- return [this._address];
- }
- /**
- * Sign a transaction with the private key. If you've added this Subprovider to your
- * app's provider, you can simply send an `eth_sendTransaction` JSON RPC request, and
- * this method will be called auto-magically. If you are not using this via a ProviderEngine
- * instance, you can call it directly.
- * @param txParams Parameters of the transaction to sign
- * @return Signed transaction hex string
- */
- public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
- PrivateKeyWalletSubprovider._validateTxParams(txParams);
- if (!_.isUndefined(txParams.from) && txParams.from !== this._address) {
- throw new Error(
- `Requested to sign transaction with address: ${txParams.from}, instantiated with address: ${
- this._address
- }`,
- );
- }
- const tx = new EthereumTx(txParams);
- tx.sign(this._privateKeyBuffer);
- const rawTx = `0x${tx.serialize().toString('hex')}`;
- return rawTx;
- }
- /**
- * Sign a personal Ethereum signed message. The signing address will be calculated from the private key.
- * The address must be provided it must match the address calculated from the private key.
- * If you've added this Subprovider to your app's provider, you can simply send an `eth_sign`
- * or `personal_sign` JSON RPC request, and this method will be called auto-magically.
- * If you are not using this via a ProviderEngine instance, you can call it directly.
- * @param data Hex string message to sign
- * @param address Address of the account to sign with
- * @return Signature hex string (order: rsv)
- */
- public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- if (_.isUndefined(data)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isHexString('data', data);
- assert.isETHAddressHex('address', address);
- if (address !== this._address) {
- throw new Error(
- `Requested to sign message with address: ${address}, instantiated with address: ${this._address}`,
- );
- }
- const dataBuff = ethUtil.toBuffer(data);
- const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
- const sig = ethUtil.ecsign(msgHashBuff, this._privateKeyBuffer);
- const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s);
- return rpcSig;
- }
- /**
- * Sign an EIP712 Typed Data message. The signing address will be calculated from the private key.
- * The address must be provided it must match the address calculated from the private key.
- * If you've added this Subprovider to your app's provider, you can simply send an `eth_signTypedData`
- * JSON RPC request, and this method will be called auto-magically.
- * If you are not using this via a ProviderEngine instance, you can call it directly.
- * @param address Address of the account to sign with
- * @param data the typed data object
- * @return Signature hex string (order: rsv)
- */
- public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
- if (_.isUndefined(typedData)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignTypedData);
- }
- assert.isETHAddressHex('address', address);
- if (address !== this._address) {
- throw new Error(
- `Requested to sign message with address: ${address}, instantiated with address: ${this._address}`,
- );
- }
- const dataBuff = signTypedDataUtils.generateTypedDataHash(typedData);
- const sig = ethUtil.ecsign(dataBuff, this._privateKeyBuffer);
- const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s);
- return rpcSig;
- }
-}
diff --git a/packages/subproviders/src/subproviders/redundant_subprovider.ts b/packages/subproviders/src/subproviders/redundant_subprovider.ts
deleted file mode 100644
index 58312f203..000000000
--- a/packages/subproviders/src/subproviders/redundant_subprovider.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { promisify } from '@0x/utils';
-import { JSONRPCRequestPayload } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { Callback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It attempts to handle each JSON RPC request by sequentially attempting to receive a valid response from one of a
- * set of JSON RPC endpoints.
- */
-export class RedundantSubprovider extends Subprovider {
- private readonly _subproviders: Subprovider[];
- private static async _firstSuccessAsync(
- subproviders: Subprovider[],
- payload: JSONRPCRequestPayload,
- next: Callback,
- ): Promise<any> {
- let lastErr: Error | undefined;
- for (const subprovider of subproviders) {
- try {
- const data = await promisify(subprovider.handleRequest.bind(subprovider))(payload, next);
- return data;
- } catch (err) {
- lastErr = err;
- continue;
- }
- }
- if (!_.isUndefined(lastErr)) {
- throw lastErr;
- }
- }
- /**
- * Instantiates a new RedundantSubprovider
- * @param subproviders Subproviders to attempt the request with
- */
- constructor(subproviders: Subprovider[]) {
- super();
- this._subproviders = subproviders;
- }
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:async-suffix
- public async handleRequest(
- payload: JSONRPCRequestPayload,
- next: Callback,
- end: (err: Error | null, data?: any) => void,
- ): Promise<void> {
- const subprovidersCopy = this._subproviders.slice();
- try {
- const data = await RedundantSubprovider._firstSuccessAsync(subprovidersCopy, payload, next);
- end(null, data);
- } catch (err) {
- end(err);
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/rpc_subprovider.ts b/packages/subproviders/src/subproviders/rpc_subprovider.ts
deleted file mode 100644
index 437518e12..000000000
--- a/packages/subproviders/src/subproviders/rpc_subprovider.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import { assert } from '@0x/assert';
-import { StatusCodes } from '@0x/types';
-import { fetchAsync } from '@0x/utils';
-import { JSONRPCRequestPayload } from 'ethereum-types';
-import JsonRpcError = require('json-rpc-error');
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It forwards on JSON RPC requests to the supplied `rpcUrl` endpoint
- */
-export class RPCSubprovider extends Subprovider {
- private readonly _rpcUrl: string;
- private readonly _requestTimeoutMs: number;
- /**
- * @param rpcUrl URL to the backing Ethereum node to which JSON RPC requests should be sent
- * @param requestTimeoutMs Amount of miliseconds to wait before timing out the JSON RPC request
- */
- constructor(rpcUrl: string, requestTimeoutMs: number = 20000) {
- super();
- assert.isString('rpcUrl', rpcUrl);
- assert.isNumber('requestTimeoutMs', requestTimeoutMs);
- this._rpcUrl = rpcUrl;
- this._requestTimeoutMs = requestTimeoutMs;
- }
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param _next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:prefer-function-over-method async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, _next: Callback, end: ErrorCallback): Promise<void> {
- const finalPayload = Subprovider._createFinalPayload(payload);
- const headers = new Headers({
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- });
-
- let response;
- try {
- response = await fetchAsync(
- this._rpcUrl,
- {
- method: 'POST',
- headers,
- body: JSON.stringify(finalPayload),
- },
- this._requestTimeoutMs,
- );
- } catch (err) {
- end(new JsonRpcError.InternalError(err));
- return;
- }
-
- const text = await response.text();
- if (!response.ok) {
- const statusCode = response.status;
- switch (statusCode) {
- case StatusCodes.MethodNotAllowed:
- end(new JsonRpcError.MethodNotFound());
- return;
- case StatusCodes.GatewayTimeout:
- const errMsg =
- 'Gateway timeout. The request took too long to process. This can happen when querying logs over too wide a block range.';
- const err = new Error(errMsg);
- end(new JsonRpcError.InternalError(err));
- return;
- default:
- end(new JsonRpcError.InternalError(text));
- return;
- }
- }
-
- let data;
- try {
- data = JSON.parse(text);
- } catch (err) {
- end(new JsonRpcError.InternalError(err));
- return;
- }
-
- if (data.error) {
- end(data.error);
- return;
- }
- end(null, data.result);
- }
-}
diff --git a/packages/subproviders/src/subproviders/signer.ts b/packages/subproviders/src/subproviders/signer.ts
deleted file mode 100644
index 9bd5cbdf1..000000000
--- a/packages/subproviders/src/subproviders/signer.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import { marshaller, Web3Wrapper } from '@0x/web3-wrapper';
-import { JSONRPCRequestPayload, Provider } from 'ethereum-types';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine)
- * subprovider interface. It forwards JSON RPC requests involving the domain of a signer (getAccounts,
- * sendTransaction, signMessage etc...) to the provider instance supplied at instantiation. All other requests
- * are passed onwards for subsequent subproviders to handle.
- */
-export class SignerSubprovider extends Subprovider {
- private readonly _web3Wrapper: Web3Wrapper;
- /**
- * Instantiates a new SignerSubprovider.
- * @param provider Web3 provider that should handle all user account related requests
- */
- constructor(provider: Provider) {
- super();
- this._web3Wrapper = new Web3Wrapper(provider);
- }
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param next Callback to call if this subprovider decides not to handle the request
- * @param end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:prefer-function-over-method async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- let message;
- let address;
- switch (payload.method) {
- case 'web3_clientVersion':
- try {
- const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
- end(null, nodeVersion);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_accounts':
- try {
- const accounts = await this._web3Wrapper.getAvailableAddressesAsync();
- end(null, accounts);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_sendTransaction':
- const [txParams] = payload.params;
- try {
- const txData = marshaller.unmarshalTxData(txParams);
- const txHash = await this._web3Wrapper.sendTransactionAsync(txData);
- end(null, txHash);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_sign':
- [address, message] = payload.params;
- try {
- const signature = await this._web3Wrapper.signMessageAsync(address, message);
- end(null, signature);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_signTypedData':
- [address, message] = payload.params;
- try {
- const signature = await this._web3Wrapper.signTypedDataAsync(address, message);
- end(null, signature);
- } catch (err) {
- end(err);
- }
- return;
- default:
- next();
- return;
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts
deleted file mode 100644
index cd6780e0c..000000000
--- a/packages/subproviders/src/subproviders/subprovider.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { promisify } from '@0x/utils';
-import { JSONRPCRequestPayload, JSONRPCResponsePayload, Provider } from 'ethereum-types';
-
-import { Callback, ErrorCallback, JSONRPCRequestPayloadWithMethod } from '../types';
-/**
- * A altered version of the base class Subprovider found in [web3-provider-engine](https://github.com/MetaMask/provider-engine).
- * This one has an async/await `emitPayloadAsync` and also defined types.
- */
-export abstract class Subprovider {
- // tslint:disable-next-line:underscore-private-and-protected
- private engine!: Provider;
- protected static _createFinalPayload(
- payload: Partial<JSONRPCRequestPayloadWithMethod>,
- ): Partial<JSONRPCRequestPayloadWithMethod> {
- const finalPayload = {
- // defaults
- id: Subprovider._getRandomId(),
- jsonrpc: '2.0',
- params: [],
- ...payload,
- };
- return finalPayload;
- }
- // Ported from: https://github.com/MetaMask/provider-engine/blob/master/util/random-id.js
- private static _getRandomId(): number {
- const extraDigits = 3;
- const baseTen = 10;
- // 13 time digits
- const datePart = new Date().getTime() * Math.pow(baseTen, extraDigits);
- // 3 random digits
- const extraPart = Math.floor(Math.random() * Math.pow(baseTen, extraDigits));
- // 16 digits
- return datePart + extraPart;
- }
- /**
- * @param payload JSON RPC request payload
- * @param next A callback to pass the request to the next subprovider in the stack
- * @param end A callback called once the subprovider is done handling the request
- */
- // tslint:disable-next-line:async-suffix
- public abstract async handleRequest(
- payload: JSONRPCRequestPayload,
- next: Callback,
- end: ErrorCallback,
- ): Promise<void>;
-
- /**
- * Emits a JSON RPC payload that will then be handled by the ProviderEngine instance
- * this subprovider is a part of. The payload will cascade down the subprovider middleware
- * stack until finding the responsible entity for handling the request.
- * @param payload JSON RPC payload
- * @returns JSON RPC response payload
- */
- public async emitPayloadAsync(payload: Partial<JSONRPCRequestPayloadWithMethod>): Promise<JSONRPCResponsePayload> {
- const finalPayload = Subprovider._createFinalPayload(payload);
- // Promisify does the binding internally and `this` is supplied as a second argument
- // tslint:disable-next-line:no-unbound-method
- const response = await promisify<JSONRPCResponsePayload>(this.engine.sendAsync, this.engine)(finalPayload);
- return response;
- }
- /**
- * Set's the subprovider's engine to the ProviderEngine it is added to.
- * This is only called within the ProviderEngine source code, do not call
- * directly.
- * @param engine The ProviderEngine this subprovider is added to
- */
- public setEngine(engine: Provider): void {
- this.engine = engine;
- }
-}
diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts
deleted file mode 100644
index ed3aea176..000000000
--- a/packages/subproviders/src/types.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-import { ECSignature } from '@0x/types';
-import { JSONRPCRequestPayload } from 'ethereum-types';
-import HDNode = require('hdkey');
-
-export interface LedgerCommunicationClient {
- close: () => Promise<void>;
-}
-
-/**
- * Elliptic Curve signature
- * The LedgerEthereumClient sends Ethereum-specific requests to the Ledger Nano S
- * It uses an internal LedgerCommunicationClient to relay these requests. Currently
- * NodeJs and Browser communication are supported.
- */
-export interface LedgerEthereumClient {
- // shouldGetChainCode is defined as `true` instead of `boolean` because other types rely on the assumption
- // that we get back the chain code and we don't have dependent types to express it properly
- getAddress: (
- derivationPath: string,
- askForDeviceConfirmation: boolean,
- shouldGetChainCode: true,
- ) => Promise<LedgerGetAddressResult>;
- signTransaction: (derivationPath: string, rawTxHex: string) => Promise<ECSignatureString>;
- signPersonalMessage: (derivationPath: string, messageHex: string) => Promise<ECSignature>;
- transport: LedgerCommunicationClient;
-}
-
-export interface ECSignatureString {
- v: string;
- r: string;
- s: string;
-}
-
-export type LedgerEthereumClientFactoryAsync = () => Promise<LedgerEthereumClient>;
-
-/**
- * networkId: The ethereum networkId to set as the chainId from EIP155
- * ledgerConnectionType: Environment in which you wish to connect to Ledger (nodejs or browser)
- * derivationPath: Initial derivation path to use e.g 44'/60'/0'
- * accountFetchingConfigs: configs related to fetching accounts from a Ledger
- */
-export interface LedgerSubproviderConfigs {
- networkId: number;
- ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync;
- baseDerivationPath?: string;
- accountFetchingConfigs?: AccountFetchingConfigs;
-}
-
-/**
- * addressSearchLimit: The maximum number of addresses to search through, defaults to 1000
- * numAddressesToReturn: Number of addresses to return from 'eth_accounts' call
- * shouldAskForOnDeviceConfirmation: Whether you wish to prompt the user on their Ledger
- * before fetching their addresses
- */
-export interface AccountFetchingConfigs {
- addressSearchLimit?: number;
- numAddressesToReturn?: number;
- shouldAskForOnDeviceConfirmation?: boolean;
-}
-
-/**
- * mnemonic: The string mnemonic seed
- * addressSearchLimit: The maximum number of addresses to search through, defaults to 1000
- * baseDerivationPath: The base derivation path (e.g 44'/60'/0'/0)
- */
-export interface MnemonicWalletSubproviderConfigs {
- mnemonic: string;
- addressSearchLimit?: number;
- baseDerivationPath?: string;
-}
-
-export interface SignatureData {
- hash: string;
- r: string;
- s: string;
- v: number;
-}
-
-export interface LedgerGetAddressResult {
- address: string;
- publicKey: string;
- chainCode: string;
-}
-
-export interface PartialTxParams {
- nonce: string;
- gasPrice?: string;
- gas: string;
- to: string;
- from: string;
- value?: string;
- data?: string;
- chainId: number; // EIP 155 chainId - mainnet: 1, ropsten: 3
-}
-
-export type DoneCallback = (err?: Error) => void;
-
-export interface LedgerCommunication {
- close_async: () => Promise<void>;
-}
-
-export interface ResponseWithTxParams {
- raw: string;
- tx: PartialTxParams;
-}
-
-export enum WalletSubproviderErrors {
- AddressNotFound = 'ADDRESS_NOT_FOUND',
- DataMissingForSignPersonalMessage = 'DATA_MISSING_FOR_SIGN_PERSONAL_MESSAGE',
- DataMissingForSignTypedData = 'DATA_MISSING_FOR_SIGN_TYPED_DATA',
- SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED',
- FromAddressMissingOrInvalid = 'FROM_ADDRESS_MISSING_OR_INVALID',
- MethodNotSupported = 'METHOD_NOT_SUPPORTED',
-}
-export enum LedgerSubproviderErrors {
- TooOldLedgerFirmware = 'TOO_OLD_LEDGER_FIRMWARE',
- MultipleOpenConnectionsDisallowed = 'MULTIPLE_OPEN_CONNECTIONS_DISALLOWED',
-}
-
-export enum NonceSubproviderErrors {
- EmptyParametersFound = 'EMPTY_PARAMETERS_FOUND',
- CannotDetermineAddressFromPayload = 'CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD',
-}
-export interface DerivedHDKeyInfo {
- address: string;
- baseDerivationPath: string;
- derivationPath: string;
- hdKey: HDNode;
-}
-
-export type ErrorCallback = (err: Error | null, data?: any) => void;
-export type Callback = () => void;
-export type OnNextCompleted = (err: Error | null, result: any, cb: Callback) => void;
-export type NextCallback = (callback?: OnNextCompleted) => void;
-
-export interface JSONRPCRequestPayloadWithMethod extends JSONRPCRequestPayload {
- method: string;
-}
diff --git a/packages/subproviders/src/utils/subprovider_utils.ts b/packages/subproviders/src/utils/subprovider_utils.ts
deleted file mode 100644
index beda408ab..000000000
--- a/packages/subproviders/src/utils/subprovider_utils.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import Web3ProviderEngine = require('web3-provider-engine');
-
-import { Subprovider } from '../subproviders/subprovider';
-
-/**
- * Prepends a subprovider to a provider
- * @param provider Given provider
- * @param subprovider Subprovider to prepend
- */
-export function prependSubprovider(provider: Web3ProviderEngine, subprovider: Subprovider): void {
- subprovider.setEngine(provider);
- // HACK: We use implementation details of provider engine here
- // https://github.com/MetaMask/provider-engine/blob/master/index.js#L68
- (provider as any)._providers = [subprovider, ...(provider as any)._providers];
-}
diff --git a/packages/subproviders/src/utils/wallet_utils.ts b/packages/subproviders/src/utils/wallet_utils.ts
deleted file mode 100644
index 7027ca8a0..000000000
--- a/packages/subproviders/src/utils/wallet_utils.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import ethUtil = require('ethereumjs-util');
-import HDNode = require('hdkey');
-
-import { DerivedHDKeyInfo } from '../types';
-
-const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000;
-
-class DerivedHDKeyInfoIterator implements IterableIterator<DerivedHDKeyInfo> {
- private readonly _parentDerivedKeyInfo: DerivedHDKeyInfo;
- private readonly _searchLimit: number;
- private _index: number;
-
- constructor(initialDerivedKey: DerivedHDKeyInfo, searchLimit: number = DEFAULT_ADDRESS_SEARCH_LIMIT) {
- this._searchLimit = searchLimit;
- this._parentDerivedKeyInfo = initialDerivedKey;
- this._index = 0;
- }
-
- public next(): IteratorResult<DerivedHDKeyInfo> {
- const baseDerivationPath = this._parentDerivedKeyInfo.baseDerivationPath;
- const derivationIndex = this._index;
- const fullDerivationPath = `m/${baseDerivationPath}/${derivationIndex}`;
- const path = `m/${derivationIndex}`;
- const hdKey = this._parentDerivedKeyInfo.hdKey.derive(path);
- const address = walletUtils.addressOfHDKey(hdKey);
- const derivedKey: DerivedHDKeyInfo = {
- address,
- hdKey,
- baseDerivationPath,
- derivationPath: fullDerivationPath,
- };
- const isDone = this._index === this._searchLimit;
- this._index++;
- return {
- done: isDone,
- value: derivedKey,
- };
- }
-
- public [Symbol.iterator](): IterableIterator<DerivedHDKeyInfo> {
- return this;
- }
-}
-
-export const walletUtils = {
- calculateDerivedHDKeyInfos(parentDerivedKeyInfo: DerivedHDKeyInfo, numberOfKeys: number): DerivedHDKeyInfo[] {
- const derivedKeys: DerivedHDKeyInfo[] = [];
- const derivedKeyIterator = new DerivedHDKeyInfoIterator(parentDerivedKeyInfo, numberOfKeys);
- for (const key of derivedKeyIterator) {
- derivedKeys.push(key);
- }
- return derivedKeys;
- },
- findDerivedKeyInfoForAddressIfExists(
- address: string,
- parentDerivedKeyInfo: DerivedHDKeyInfo,
- searchLimit: number,
- ): DerivedHDKeyInfo | undefined {
- const lowercaseAddress = address.toLowerCase();
- let matchedKey: DerivedHDKeyInfo | undefined;
- const derivedKeyIterator = new DerivedHDKeyInfoIterator(parentDerivedKeyInfo, searchLimit);
- for (const key of derivedKeyIterator) {
- if (key.address === lowercaseAddress) {
- matchedKey = key;
- break;
- }
- }
- return matchedKey;
- },
- addressOfHDKey(hdKey: HDNode): string {
- const shouldSanitizePublicKey = true;
- const derivedPublicKey = hdKey.publicKey;
- const ethereumAddressUnprefixed = ethUtil
- .publicToAddress(derivedPublicKey, shouldSanitizePublicKey)
- .toString('hex');
- const address = ethUtil.addHexPrefix(ethereumAddressUnprefixed).toLowerCase();
- return address;
- },
-};
diff --git a/packages/subproviders/test/chai_setup.ts b/packages/subproviders/test/chai_setup.ts
deleted file mode 100644
index 6c24dc222..000000000
--- a/packages/subproviders/test/chai_setup.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import * as chai from 'chai';
-import chaiAsPromised = require('chai-as-promised');
-import * as dirtyChai from 'dirty-chai';
-
-export const chaiSetup = {
- configure(): void {
- chai.config.includeStack = true;
- chai.use(dirtyChai);
- chai.use(chaiAsPromised);
- },
-};
diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts
deleted file mode 100644
index b072e611b..000000000
--- a/packages/subproviders/test/integration/ledger_subprovider_test.ts
+++ /dev/null
@@ -1,205 +0,0 @@
-import { DoneCallback } from '@0x/types';
-import { promisify } from '@0x/utils';
-import Eth from '@ledgerhq/hw-app-eth';
-// HACK: This dependency is optional and tslint skips optional dependencies
-// tslint:disable-next-line:no-implicit-dependencies
-import TransportNodeHid from '@ledgerhq/hw-transport-node-hid';
-import * as chai from 'chai';
-import { JSONRPCResponsePayload } from 'ethereum-types';
-import * as ethUtils from 'ethereumjs-util';
-
-import { LedgerSubprovider, RPCSubprovider, Web3ProviderEngine } from '../../src';
-import { LedgerEthereumClient } from '../../src/types';
-import { chaiSetup } from '../chai_setup';
-import { fixtureData } from '../utils/fixture_data';
-import { reportCallbackErrors } from '../utils/report_callback_errors';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const DEFAULT_NUM_ACCOUNTS = 10;
-const EXPECTED_SIGNATURE_LENGTH = 132;
-
-async function ledgerEthereumNodeJsClientFactoryAsync(): Promise<LedgerEthereumClient> {
- const ledgerConnection = await TransportNodeHid.create();
- const ledgerEthClient = new Eth(ledgerConnection);
- return ledgerEthClient;
-}
-
-describe('LedgerSubprovider', () => {
- let ledgerSubprovider: LedgerSubprovider;
- const networkId: number = fixtureData.NETWORK_ID;
- before(async () => {
- ledgerSubprovider = new LedgerSubprovider({
- networkId,
- ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync,
- baseDerivationPath: fixtureData.TESTRPC_BASE_DERIVATION_PATH,
- });
- });
- describe('direct method calls', () => {
- it('returns default number of accounts', async () => {
- const accounts = await ledgerSubprovider.getAccountsAsync();
- expect(accounts[0]).to.not.be.an('undefined');
- expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- });
- it('returns the expected accounts from a ledger set up with the test mnemonic', async () => {
- const accounts = await ledgerSubprovider.getAccountsAsync();
- expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
- expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1);
- });
- it('returns requested number of accounts', async () => {
- const numberOfAccounts = 20;
- const accounts = await ledgerSubprovider.getAccountsAsync(numberOfAccounts);
- expect(accounts[0]).to.not.be.an('undefined');
- expect(accounts.length).to.be.equal(numberOfAccounts);
- });
- it('signs a personal message', async () => {
- const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(
- data,
- fixtureData.TEST_RPC_ACCOUNT_0,
- );
- expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- });
- it('signs a personal message with second address', async () => {
- const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(
- data,
- fixtureData.TEST_RPC_ACCOUNT_1,
- );
- expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_ACCOUNT_1_SIGNED_RESULT);
- });
- it('signs a transaction', async () => {
- const txHex = await ledgerSubprovider.signTransactionAsync(fixtureData.TX_DATA);
- expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
- });
- it('signs a transaction with the second address', async () => {
- const txData = { ...fixtureData.TX_DATA, from: fixtureData.TEST_RPC_ACCOUNT_1 };
- const txHex = await ledgerSubprovider.signTransactionAsync(txData);
- expect(txHex).to.be.equal(fixtureData.TX_DATA_ACCOUNT_1_SIGNED_RESULT);
- });
- });
- describe('calls through a provider', () => {
- let defaultProvider: Web3ProviderEngine;
- let ledgerProvider: Web3ProviderEngine;
- before(() => {
- ledgerProvider = new Web3ProviderEngine();
- ledgerProvider.addProvider(ledgerSubprovider);
- const httpProvider = new RPCSubprovider('http://localhost:8545');
- ledgerProvider.addProvider(httpProvider);
- ledgerProvider.start();
-
- defaultProvider = new Web3ProviderEngine();
- defaultProvider.addProvider(httpProvider);
- defaultProvider.start();
- });
- it('returns a list of accounts', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_accounts',
- params: [],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- done();
- });
- ledgerProvider.sendAsync(payload, callback);
- });
- it('signs a personal message with eth_sign', (done: DoneCallback) => {
- (async () => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
- const accounts = await ledgerSubprovider.getAccountsAsync();
- const signer = accounts[0];
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [signer, messageHex],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.length).to.be.equal(EXPECTED_SIGNATURE_LENGTH);
- expect(response.result.substr(0, 2)).to.be.equal('0x');
- done();
- });
- ledgerProvider.sendAsync(payload, callback);
- })().catch(done);
- });
- it('signs a personal message with personal_sign', (done: DoneCallback) => {
- (async () => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
- const accounts = await ledgerSubprovider.getAccountsAsync();
- const signer = accounts[0];
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [messageHex, signer],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.length).to.be.equal(EXPECTED_SIGNATURE_LENGTH);
- expect(response.result.substr(0, 2)).to.be.equal('0x');
- done();
- });
- ledgerProvider.sendAsync(payload, callback);
- })().catch(done);
- });
- it('signs a transaction', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_signTransaction',
- params: [fixtureData.TX_DATA],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.raw).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
- done();
- });
- ledgerProvider.sendAsync(payload, callback);
- });
- it('signs and sends a transaction', (done: DoneCallback) => {
- (async () => {
- const accounts = await ledgerSubprovider.getAccountsAsync();
-
- // Give first account on Ledger sufficient ETH to complete tx send
- let tx = {
- to: accounts[0],
- from: fixtureData.TEST_RPC_ACCOUNT_0,
- value: '0x8ac7230489e80000', // 10 ETH
- };
- let payload = {
- jsonrpc: '2.0',
- method: 'eth_sendTransaction',
- params: [tx],
- id: 1,
- };
- await promisify(defaultProvider.sendAsync.bind(defaultProvider))(payload);
-
- // Send transaction from Ledger
- tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- from: accounts[0],
- value: '0xde0b6b3a7640000',
- };
- payload = {
- jsonrpc: '2.0',
- method: 'eth_sendTransaction',
- params: [tx],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- const result = response.result;
- const signedTxLength = 66;
- expect(result.length).to.be.equal(signedTxLength);
- expect(result.substr(0, 2)).to.be.equal('0x');
- done();
- });
- ledgerProvider.sendAsync(payload, callback);
- })().catch(done);
- });
- });
-});
diff --git a/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts b/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts
deleted file mode 100644
index 49698ce9e..000000000
--- a/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-import * as chai from 'chai';
-import * as lightwallet from 'eth-lightwallet';
-import { JSONRPCResponsePayload } from 'ethereum-types';
-import * as ethUtils from 'ethereumjs-util';
-
-import { EthLightwalletSubprovider, Web3ProviderEngine } from '../../src';
-import { DoneCallback } from '../../src/types';
-import { chaiSetup } from '../chai_setup';
-import { fixtureData } from '../utils/fixture_data';
-import { ganacheSubprovider } from '../utils/ganache_subprovider';
-import { reportCallbackErrors } from '../utils/report_callback_errors';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-const DEFAULT_NUM_ACCOUNTS = 10;
-const PASSWORD = 'supersecretpassword99';
-const SALT = 'kvODghzs7Ff1uqHyI0P3wI4Hso4w4iWT2e9qmrWz0y4';
-
-describe('EthLightwalletSubprovider', () => {
- let ethLightwalletSubprovider: EthLightwalletSubprovider;
- before(async () => {
- const options = {
- password: PASSWORD,
- seedPhrase: fixtureData.TEST_RPC_MNEMONIC,
- salt: SALT,
- hdPathString: fixtureData.TESTRPC_BASE_DERIVATION_PATH,
- };
- const createVaultAsync = async (vaultOptions: lightwallet.VaultOptions) => {
- return new Promise<lightwallet.keystore>(resolve => {
- lightwallet.keystore.createVault(vaultOptions, (err: Error, vaultKeystore) => {
- if (err) {
- throw new Error(`Failed to createVault: ${err}`);
- }
- resolve(vaultKeystore);
- });
- });
- };
- const deriveKeyFromPasswordAsync = async (vaultKeystore: lightwallet.keystore) => {
- return new Promise<Uint8Array>(resolve => {
- vaultKeystore.keyFromPassword(PASSWORD, (err: Error, passwordDerivedKey: Uint8Array) => {
- if (err) {
- throw new Error(`Failed to get key from password: ${err}`);
- }
- resolve(passwordDerivedKey);
- });
- });
- };
- const keystore: lightwallet.keystore = await createVaultAsync(options);
- const pwDerivedKey: Uint8Array = await deriveKeyFromPasswordAsync(keystore);
-
- // Generate 10 addresses
- keystore.generateNewAddress(pwDerivedKey, DEFAULT_NUM_ACCOUNTS);
-
- ethLightwalletSubprovider = new EthLightwalletSubprovider(keystore, pwDerivedKey);
- });
- describe('direct method calls', () => {
- describe('success cases', () => {
- it('returns a list of accounts', async () => {
- const accounts = await ethLightwalletSubprovider.getAccountsAsync();
- expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
- expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1);
- expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- });
- it('signs a personal message hash', async () => {
- const accounts = await ethLightwalletSubprovider.getAccountsAsync();
- const signingAccount = accounts[0];
- const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const ecSignatureHex = await ethLightwalletSubprovider.signPersonalMessageAsync(data, signingAccount);
- expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- });
- it('signs a transaction', async () => {
- const txHex = await ethLightwalletSubprovider.signTransactionAsync(fixtureData.TX_DATA);
- expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
- });
- it('signs an EIP712 sign typed data message', async () => {
- const signature = await ethLightwalletSubprovider.signTypedDataAsync(
- fixtureData.TEST_RPC_ACCOUNT_0,
- fixtureData.EIP712_TEST_TYPED_DATA,
- );
- expect(signature).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
- });
- });
- });
- describe('calls through a provider', () => {
- let provider: Web3ProviderEngine;
- before(() => {
- provider = new Web3ProviderEngine();
- provider.addProvider(ethLightwalletSubprovider);
- provider.addProvider(ganacheSubprovider);
- provider.start();
- });
- describe('success cases', () => {
- it('returns a list of accounts', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_accounts',
- params: [],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
- expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a personal message hash with eth_sign', (done: DoneCallback) => {
- const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const account = fixtureData.TEST_RPC_ACCOUNT_0;
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [account, data],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a transaction', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_signTransaction',
- params: [fixtureData.TX_DATA],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.raw).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs an EIP712 sign typed data message with eth_signTypedData', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_signTypedData',
- params: [fixtureData.TEST_RPC_ACCOUNT_0, fixtureData.EIP712_TEST_TYPED_DATA],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- });
- describe('failure cases', () => {
- it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
- const nonHexMessage = 'hello world';
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => {
- const nonHexMessage = 'hello world';
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- });
- });
-});
diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts
deleted file mode 100644
index a1d146dbc..000000000
--- a/packages/subproviders/test/unit/ledger_subprovider_test.ts
+++ /dev/null
@@ -1,255 +0,0 @@
-import * as chai from 'chai';
-import { JSONRPCResponsePayload } from 'ethereum-types';
-import * as ethUtils from 'ethereumjs-util';
-import * as _ from 'lodash';
-
-import { LedgerSubprovider, Web3ProviderEngine } from '../../src';
-import {
- DoneCallback,
- LedgerCommunicationClient,
- LedgerSubproviderErrors,
- WalletSubproviderErrors,
-} from '../../src/types';
-import { chaiSetup } from '../chai_setup';
-import { fixtureData } from '../utils/fixture_data';
-import { ganacheSubprovider } from '../utils/ganache_subprovider';
-import { reportCallbackErrors } from '../utils/report_callback_errors';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const FAKE_ADDRESS = '0xb088a3bc93f71b4de97b9de773e9647645983688';
-const DEFAULT_NUM_ACCOUNTS = 10;
-
-describe('LedgerSubprovider', () => {
- const networkId: number = 42;
- let ledgerSubprovider: LedgerSubprovider;
- before(async () => {
- const ledgerEthereumClientFactoryAsync = async () => {
- // tslint:disable:no-object-literal-type-assertion
- const ledgerEthClient = {
- getAddress: async () => {
- const publicKey =
- '04f428290f4c5ed6a198f71b8205f488141dbb3f0840c923bbfa798ecbee6370986c03b5575d94d506772fb48a6a44e345e4ebd4f028a6f609c44b655d6d3e71a1';
- const chainCode = 'ac055a5537c0c7e9e02d14a197cad6b857836da2a12043b46912a37d959b5ae8';
- const address = '0xBa388BA5e5EEF2c6cE42d831c2B3A28D3c99bdB1';
- return {
- publicKey,
- address,
- chainCode,
- };
- },
- signPersonalMessage: async () => {
- const ecSignature = {
- v: 28,
- r: 'a6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae49148',
- s: '0652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d0',
- };
- return ecSignature;
- },
- signTransaction: async (_derivationPath: string, _txHex: string) => {
- const ecSignature = {
- v: '77',
- r: '88a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98b',
- s: '019f4a4b9a107d1e6752bf7f701e275f28c13791d6e76af895b07373462cefaa',
- };
- return ecSignature;
- },
- transport: {
- close: _.noop.bind(_),
- } as LedgerCommunicationClient,
- };
- // tslint:enable:no-object-literal-type-assertion
- return ledgerEthClient;
- };
- ledgerSubprovider = new LedgerSubprovider({
- networkId,
- ledgerEthereumClientFactoryAsync,
- });
- });
- describe('direct method calls', () => {
- describe('success cases', () => {
- it('returns default number of accounts', async () => {
- const accounts = await ledgerSubprovider.getAccountsAsync();
- expect(accounts[0]).to.be.equal(FAKE_ADDRESS);
- expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- });
- it('returns requested number of accounts', async () => {
- const numberOfAccounts = 20;
- const accounts = await ledgerSubprovider.getAccountsAsync(numberOfAccounts);
- expect(accounts[0]).to.be.equal(FAKE_ADDRESS);
- expect(accounts.length).to.be.equal(numberOfAccounts);
- });
- it('signs a personal message', async () => {
- const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data, FAKE_ADDRESS);
- expect(ecSignatureHex).to.be.equal(
- '0xa6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae491480652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d001',
- );
- });
- });
- describe('failure cases', () => {
- it('cannot open multiple simultaneous connections to the Ledger device', async () => {
- const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
- return expect(
- Promise.all([
- ledgerSubprovider.getAccountsAsync(),
- ledgerSubprovider.signPersonalMessageAsync(data, FAKE_ADDRESS),
- ]),
- ).to.be.rejectedWith(LedgerSubproviderErrors.MultipleOpenConnectionsDisallowed);
- });
- });
- });
- describe('calls through a provider', () => {
- let provider: Web3ProviderEngine;
- before(() => {
- provider = new Web3ProviderEngine();
- provider.addProvider(ledgerSubprovider);
- provider.addProvider(ganacheSubprovider);
- provider.start();
- });
- describe('success cases', () => {
- it('returns a list of accounts', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_accounts',
- params: [],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- expect(response.result[0]).to.be.equal(FAKE_ADDRESS);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a personal message with eth_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [FAKE_ADDRESS, messageHex],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(
- '0xa6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae491480652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d001',
- );
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a personal message with personal_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [messageHex, FAKE_ADDRESS],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(
- '0xa6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae491480652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d001',
- );
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a transaction', (done: DoneCallback) => {
- const tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- value: '0x00',
- gasPrice: '0x00',
- nonce: '0x00',
- gas: '0x00',
- from: FAKE_ADDRESS,
- };
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_signTransaction',
- params: [tx],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- const rawTxLength = 192;
- expect(response.result.raw.length).to.be.equal(rawTxLength);
- expect(response.result.raw.substr(0, 2)).to.be.equal('0x');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- });
- describe('failure cases', () => {
- it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
- const nonHexMessage = 'hello world';
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [FAKE_ADDRESS, nonHexMessage],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => {
- const nonHexMessage = 'hello world';
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [nonHexMessage, FAKE_ADDRESS],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `from` param missing when calling eth_sendTransaction', (done: DoneCallback) => {
- const tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- value: '0xde0b6b3a7640000',
- };
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sendTransaction',
- params: [tx],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `from` param invalid address when calling eth_sendTransaction', (done: DoneCallback) => {
- const tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- from: '0xIncorrectEthereumAddress',
- value: '0xde0b6b3a7640000',
- };
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sendTransaction',
- params: [tx],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- });
- });
-});
diff --git a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts
deleted file mode 100644
index 61dcbf6da..000000000
--- a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts
+++ /dev/null
@@ -1,230 +0,0 @@
-import * as chai from 'chai';
-import { JSONRPCResponsePayload } from 'ethereum-types';
-import * as ethUtils from 'ethereumjs-util';
-
-import { GanacheSubprovider, MnemonicWalletSubprovider, Web3ProviderEngine } from '../../src/';
-import { DoneCallback, WalletSubproviderErrors } from '../../src/types';
-import { chaiSetup } from '../chai_setup';
-import { fixtureData } from '../utils/fixture_data';
-import { reportCallbackErrors } from '../utils/report_callback_errors';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const DEFAULT_NUM_ACCOUNTS = 10;
-
-describe('MnemonicWalletSubprovider', () => {
- let subprovider: MnemonicWalletSubprovider;
- before(async () => {
- subprovider = new MnemonicWalletSubprovider({
- mnemonic: fixtureData.TEST_RPC_MNEMONIC,
- baseDerivationPath: fixtureData.TEST_RPC_MNEMONIC_BASE_DERIVATION_PATH,
- });
- });
- describe('direct method calls', () => {
- describe('success cases', () => {
- it('returns the accounts', async () => {
- const accounts = await subprovider.getAccountsAsync();
- expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
- expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1);
- expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- });
- it('signs a personal message', async () => {
- const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const ecSignatureHex = await subprovider.signPersonalMessageAsync(data, fixtureData.TEST_RPC_ACCOUNT_0);
- expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- });
- it('signs a personal message with second address', async () => {
- const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const ecSignatureHex = await subprovider.signPersonalMessageAsync(data, fixtureData.TEST_RPC_ACCOUNT_1);
- expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_ACCOUNT_1_SIGNED_RESULT);
- });
- it('signs a transaction', async () => {
- const txHex = await subprovider.signTransactionAsync(fixtureData.TX_DATA);
- expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
- });
- it('signs a transaction with the second address', async () => {
- const txData = { ...fixtureData.TX_DATA, from: fixtureData.TEST_RPC_ACCOUNT_1 };
- const txHex = await subprovider.signTransactionAsync(txData);
- expect(txHex).to.be.equal(fixtureData.TX_DATA_ACCOUNT_1_SIGNED_RESULT);
- });
- it('signs an EIP712 sign typed data message', async () => {
- const signature = await subprovider.signTypedDataAsync(
- fixtureData.TEST_RPC_ACCOUNT_0,
- fixtureData.EIP712_TEST_TYPED_DATA,
- );
- expect(signature).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
- });
- });
- describe('failure cases', () => {
- it('throws an error if address is invalid ', async () => {
- const txData = { ...fixtureData.TX_DATA, from: '0x0' };
- return expect(subprovider.signTransactionAsync(txData)).to.be.rejectedWith(
- WalletSubproviderErrors.FromAddressMissingOrInvalid,
- );
- });
- it('throws an error if address is valid format but not found', async () => {
- const txData = { ...fixtureData.TX_DATA, from: fixtureData.NULL_ADDRESS };
- return expect(subprovider.signTransactionAsync(txData)).to.be.rejectedWith(
- `${WalletSubproviderErrors.AddressNotFound}: ${fixtureData.NULL_ADDRESS}`,
- );
- });
- });
- });
- describe('calls through a provider', () => {
- let provider: Web3ProviderEngine;
- before(() => {
- provider = new Web3ProviderEngine();
- provider.addProvider(subprovider);
- const ganacheSubprovider = new GanacheSubprovider({});
- provider.addProvider(ganacheSubprovider);
- provider.start();
- });
- describe('success cases', () => {
- it('returns a list of accounts', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_accounts',
- params: [],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
- expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a personal message with eth_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [fixtureData.TEST_RPC_ACCOUNT_0, messageHex],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a personal message with personal_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [messageHex, fixtureData.TEST_RPC_ACCOUNT_0],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs an EIP712 sign typed data message with eth_signTypedData', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_signTypedData',
- params: [fixtureData.TEST_RPC_ACCOUNT_0, fixtureData.EIP712_TEST_TYPED_DATA],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- });
- describe('failure cases', () => {
- it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
- const nonHexMessage = 'hello world';
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => {
- const nonHexMessage = 'hello world';
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `address` param not found when calling personal_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [messageHex, fixtureData.NULL_ADDRESS],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(
- `${WalletSubproviderErrors.AddressNotFound}: ${fixtureData.NULL_ADDRESS}`,
- );
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `from` param missing when calling eth_sendTransaction', (done: DoneCallback) => {
- const tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- value: '0xde0b6b3a7640000',
- };
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sendTransaction',
- params: [tx],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `from` param invalid address when calling eth_sendTransaction', (done: DoneCallback) => {
- const tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- from: '0xIncorrectEthereumAddress',
- value: '0xde0b6b3a7640000',
- };
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sendTransaction',
- params: [tx],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- });
- });
-});
diff --git a/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts b/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts
deleted file mode 100644
index a5cef30dc..000000000
--- a/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts
+++ /dev/null
@@ -1,149 +0,0 @@
-import * as chai from 'chai';
-import FixtureSubprovider = require('web3-provider-engine/subproviders/fixture');
-
-import { promisify } from '@0x/utils';
-import EthereumTx = require('ethereumjs-tx');
-
-import { NonceTrackerSubprovider, Web3ProviderEngine } from '../../src';
-import { chaiSetup } from '../chai_setup';
-
-const expect = chai.expect;
-chaiSetup.configure();
-
-describe('NonceTrackerSubprovider', () => {
- let provider: Web3ProviderEngine;
- const getTransactionCountPayload = {
- jsonrpc: '2.0',
- method: 'eth_getTransactionCount',
- params: ['0x0', 'pending'],
- id: 1,
- };
- const sendTransactionPayload = {
- jsonrpc: '2.0',
- method: 'eth_sendRawTransaction',
- params: [],
- id: 1,
- };
- const txParams = [
- '0x',
- '0x09184e72a000',
- '0x2710',
- '0x0000000000000000000000000000000000000000',
- '0x',
- '0x7f7465737432000000000000000000000000000000000000000000000000000000600057',
- '0x1c',
- '0x5e1d3a76fbf824220eafc8c79ad578ad2b67d01b0c2425eb1f1347e8f50882ab',
- '0x5bd428537f05f9830e93792f90ea6a3e2d1ee84952dd96edbae9f658f831ab13',
- ];
- function createFixtureSubprovider(): FixtureSubprovider {
- let isFirstGetTransactionCount = true;
- const fixedBlockNumberAndTransactionCountProvider = new FixtureSubprovider({
- eth_getBlockByNumber: '0x01',
- eth_getTransactionCount: (_data: any, _next: any, end: any) => {
- // For testing caching we return different results on the second call
- if (isFirstGetTransactionCount) {
- isFirstGetTransactionCount = false;
- end(null, '0x00');
- } else {
- end(null, '0x99');
- }
- },
- });
- return fixedBlockNumberAndTransactionCountProvider;
- }
- it('successfully caches the transaction count', async () => {
- provider = new Web3ProviderEngine();
- const nonceTrackerSubprovider = new NonceTrackerSubprovider();
- provider.addProvider(nonceTrackerSubprovider);
- provider.addProvider(createFixtureSubprovider());
- provider.start();
-
- const payload = { ...getTransactionCountPayload, params: ['0x0', 'pending'] };
-
- const response = await promisify<any>(provider.sendAsync.bind(provider))(payload);
- expect(response.result).to.be.eq('0x00');
- const secondResponse = await promisify<any>(provider.sendAsync.bind(provider))(payload);
- expect(secondResponse.result).to.be.eq('0x00');
- });
- it('does not cache the result for latest transaction count', async () => {
- provider = new Web3ProviderEngine();
- const nonceTrackerSubprovider = new NonceTrackerSubprovider();
- provider.addProvider(nonceTrackerSubprovider);
- provider.addProvider(createFixtureSubprovider());
- provider.start();
-
- const payload = { ...getTransactionCountPayload, params: ['0x0', 'latest'] };
-
- const response = await promisify<any>(provider.sendAsync.bind(provider))(payload);
- expect(response.result).to.be.eq('0x00');
- const secondResponse = await promisify<any>(provider.sendAsync.bind(provider))(payload);
- expect(secondResponse.result).to.be.eq('0x99');
- });
- it('clears the cache on a Nonce Too Low Error', async () => {
- provider = new Web3ProviderEngine();
- const nonceTrackerSubprovider = new NonceTrackerSubprovider();
- provider.addProvider(nonceTrackerSubprovider);
- provider.addProvider(createFixtureSubprovider());
- provider.addProvider(
- new FixtureSubprovider({
- eth_sendRawTransaction: (_data: any, _next: any, end: any) => {
- end(new Error('Transaction nonce is too low'));
- },
- }),
- );
- provider.start();
-
- const noncePayload = {
- ...getTransactionCountPayload,
- params: ['0x1f36f546477cda21bf2296c50976f2740247906f', 'pending'],
- };
- const transaction = new EthereumTx(txParams);
- const txPayload = {
- ...sendTransactionPayload,
- params: [transaction.serialize()],
- };
-
- const response = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload);
- expect(response.result).to.be.eq('0x00');
- const secondResponse = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload);
- expect(secondResponse.result).to.be.eq('0x00');
- try {
- await promisify(provider.sendAsync.bind(provider))(txPayload);
- } catch (err) {
- const thirdResponse = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload);
- expect(thirdResponse.result).to.be.eq('0x99');
- }
- });
- it('increments the used nonce when a transaction successfully submits', async () => {
- provider = new Web3ProviderEngine();
- const nonceTrackerSubprovider = new NonceTrackerSubprovider();
- provider.addProvider(nonceTrackerSubprovider);
- provider.addProvider(createFixtureSubprovider());
- provider.addProvider(
- new FixtureSubprovider({
- eth_sendRawTransaction: (_data: any, _next: any, end: any) => {
- end(null);
- },
- }),
- );
- provider.start();
-
- const noncePayload = {
- ...getTransactionCountPayload,
- params: ['0x1f36f546477cda21bf2296c50976f2740247906f', 'pending'],
- };
- const transaction = new EthereumTx(txParams);
- const txPayload = {
- ...sendTransactionPayload,
- params: [transaction.serialize()],
- };
-
- const response = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload);
- expect(response.result).to.be.eq('0x00');
- const secondResponse = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload);
- expect(secondResponse.result).to.be.eq('0x00');
- await promisify(provider.sendAsync.bind(provider))(txPayload);
- const thirdResponse = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload);
- expect(thirdResponse.result).to.be.eq('0x01');
- });
-});
diff --git a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts
deleted file mode 100644
index 4cd70e5ed..000000000
--- a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts
+++ /dev/null
@@ -1,232 +0,0 @@
-import * as chai from 'chai';
-import { JSONRPCResponsePayload } from 'ethereum-types';
-import * as ethUtils from 'ethereumjs-util';
-
-import { GanacheSubprovider, PrivateKeyWalletSubprovider, Web3ProviderEngine } from '../../src/';
-import { DoneCallback, WalletSubproviderErrors } from '../../src/types';
-import { chaiSetup } from '../chai_setup';
-import { fixtureData } from '../utils/fixture_data';
-import { reportCallbackErrors } from '../utils/report_callback_errors';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-describe('PrivateKeyWalletSubprovider', () => {
- let subprovider: PrivateKeyWalletSubprovider;
- before(async () => {
- subprovider = new PrivateKeyWalletSubprovider(fixtureData.TEST_RPC_ACCOUNT_0_ACCOUNT_PRIVATE_KEY);
- });
- describe('direct method calls', () => {
- describe('success cases', () => {
- it('returns the account', async () => {
- const accounts = await subprovider.getAccountsAsync();
- expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
- expect(accounts.length).to.be.equal(1);
- });
- it('signs a personal message', async () => {
- const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const ecSignatureHex = await subprovider.signPersonalMessageAsync(data, fixtureData.TEST_RPC_ACCOUNT_0);
- expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- });
- it('signs a transaction', async () => {
- const txHex = await subprovider.signTransactionAsync(fixtureData.TX_DATA);
- expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
- });
- it('signs an EIP712 sign typed data message', async () => {
- const signature = await subprovider.signTypedDataAsync(
- fixtureData.TEST_RPC_ACCOUNT_0,
- fixtureData.EIP712_TEST_TYPED_DATA,
- );
- expect(signature).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
- });
- });
- });
- describe('calls through a provider', () => {
- let provider: Web3ProviderEngine;
- before(() => {
- provider = new Web3ProviderEngine();
- provider.addProvider(subprovider);
- const ganacheSubprovider = new GanacheSubprovider({});
- provider.addProvider(ganacheSubprovider);
- provider.start();
- });
- describe('success cases', () => {
- it('returns a list of accounts', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_accounts',
- params: [],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
- expect(response.result.length).to.be.equal(1);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a transaction', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_signTransaction',
- params: [fixtureData.TX_DATA],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.raw).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a personal message with eth_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [fixtureData.TEST_RPC_ACCOUNT_0, messageHex],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs a personal message with personal_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [messageHex, fixtureData.TEST_RPC_ACCOUNT_0],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('signs an EIP712 sign typed data message with eth_signTypedData', (done: DoneCallback) => {
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_signTypedData',
- params: [fixtureData.TEST_RPC_ACCOUNT_0, fixtureData.EIP712_TEST_TYPED_DATA],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- });
- describe('failure cases', () => {
- it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
- const nonHexMessage = 'hello world';
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sign',
- params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => {
- const nonHexMessage = 'hello world';
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `address` param is not the address from private key when calling personal_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [messageHex, fixtureData.TEST_RPC_ACCOUNT_1],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(
- `Requested to sign message with address: ${
- fixtureData.TEST_RPC_ACCOUNT_1
- }, instantiated with address: ${fixtureData.TEST_RPC_ACCOUNT_0}`,
- );
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `from` param missing when calling eth_sendTransaction', (done: DoneCallback) => {
- const tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- value: '0xde0b6b3a7640000',
- };
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sendTransaction',
- params: [tx],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `from` param invalid address when calling eth_sendTransaction', (done: DoneCallback) => {
- const tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- from: '0xIncorrectEthereumAddress',
- value: '0xde0b6b3a7640000',
- };
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_sendTransaction',
- params: [tx],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('should throw if `address` param not found when calling personal_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [messageHex, '0x0'],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(`Expected address to be of type ETHAddressHex, encountered: 0x0`);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- });
- });
-});
diff --git a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts
deleted file mode 100644
index fb4e43f9e..000000000
--- a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { DoneCallback } from '@0x/types';
-import * as chai from 'chai';
-import { JSONRPCResponsePayload } from 'ethereum-types';
-import * as Sinon from 'sinon';
-
-import { RedundantSubprovider, RPCSubprovider, Web3ProviderEngine } from '../../src';
-import { Subprovider } from '../../src/subproviders/subprovider';
-import { chaiSetup } from '../chai_setup';
-import { ganacheSubprovider } from '../utils/ganache_subprovider';
-import { reportCallbackErrors } from '../utils/report_callback_errors';
-
-const expect = chai.expect;
-chaiSetup.configure();
-const DEFAULT_NUM_ACCOUNTS = 10;
-
-describe('RedundantSubprovider', () => {
- let provider: Web3ProviderEngine;
- it('succeeds when supplied a healthy endpoint', (done: DoneCallback) => {
- provider = new Web3ProviderEngine();
- const subproviders = [ganacheSubprovider];
- const redundantSubprovider = new RedundantSubprovider(subproviders);
- provider.addProvider(redundantSubprovider);
- provider.start();
-
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_accounts',
- params: [],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- done();
- });
- provider.sendAsync(payload, callback);
- });
- it('succeeds when supplied at least one healthy endpoint', (done: DoneCallback) => {
- provider = new Web3ProviderEngine();
- const nonExistentSubprovider = new RPCSubprovider('http://does-not-exist:3000');
- const handleRequestStub = Sinon.stub(nonExistentSubprovider, 'handleRequest').throws(
- new Error('REQUEST_FAILED'),
- );
- const subproviders = [nonExistentSubprovider as Subprovider, ganacheSubprovider];
- const redundantSubprovider = new RedundantSubprovider(subproviders);
- provider.addProvider(redundantSubprovider);
- provider.start();
-
- const payload = {
- jsonrpc: '2.0',
- method: 'eth_accounts',
- params: [],
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- expect(err).to.be.a('null');
- expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
- handleRequestStub.restore();
- done();
- });
- provider.sendAsync(payload, callback);
- });
-});
diff --git a/packages/subproviders/test/utils/configs.ts b/packages/subproviders/test/utils/configs.ts
deleted file mode 100644
index 341037e4f..000000000
--- a/packages/subproviders/test/utils/configs.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const configs = {
- port: 8545,
- networkId: 50,
- mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic',
-};
diff --git a/packages/subproviders/test/utils/fixture_data.ts b/packages/subproviders/test/utils/fixture_data.ts
deleted file mode 100644
index 3eb4493b5..000000000
--- a/packages/subproviders/test/utils/fixture_data.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
-const TEST_RPC_ACCOUNT_1 = '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb';
-const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
-const networkId = 42;
-export const fixtureData = {
- NULL_ADDRESS,
- TEST_RPC_ACCOUNT_0,
- TEST_RPC_ACCOUNT_0_ACCOUNT_PRIVATE_KEY: 'F2F48EE19680706196E2E339E5DA3491186E0C4C5030670656B0E0164837257D',
- TEST_RPC_ACCOUNT_1,
- TEST_RPC_MNEMONIC: 'concert load couple harbor equip island argue ramp clarify fence smart topic',
- TEST_RPC_MNEMONIC_BASE_DERIVATION_PATH: `44'/60'/0'/0`,
- PERSONAL_MESSAGE_STRING: 'hello world',
- PERSONAL_MESSAGE_SIGNED_RESULT:
- '0x1b0ec5e2908e993d0c8ab6b46da46be2688fdf03c7ea6686075de37392e50a7d7fcc531446699132fbda915bd989882e0064d417018773a315fb8d43ed063c9b00',
- PERSONAL_MESSAGE_ACCOUNT_1_SIGNED_RESULT:
- '0xe7ae0c21d02eb38f2c2a20d9d7876a98cc7ef035b7a4559d49375e2ec735e06f0d0ab0ff92ee56c5ffc28d516e6ed0692d0270feae8796408dbef060c6c7100f01',
- TESTRPC_BASE_DERIVATION_PATH: `m/44'/60'/0'/0`,
- NETWORK_ID: networkId,
- TX_DATA: {
- nonce: '0x00',
- gasPrice: '0x0',
- gas: '0x2710',
- to: NULL_ADDRESS,
- value: '0x00',
- chainId: networkId,
- from: TEST_RPC_ACCOUNT_0,
- },
- // This is the signed result of the above Transaction Data
- TX_DATA_SIGNED_RESULT:
- '0xf85f8080822710940000000000000000000000000000000000000000808078a0712854c73c69445cc1b22a7c3d7312ff9a97fe4ffba35fd636e8236b211b6e7ca0647cee031615e52d916c7c707025bc64ad525d8f1b9876c3435a863b42743178',
- TX_DATA_ACCOUNT_1_SIGNED_RESULT:
- '0xf85f8080822710940000000000000000000000000000000000000000808078a04b02af7ff3f18ce114b601542cc8ebdc50921354f75dd510d31793453a0710e6a0540082a01e475465801b8186a2edc79ec1a2dcf169b9781c25a58a417023c9ca',
- EIP712_TEST_TYPED_DATA: {
- types: {
- EIP712Domain: [
- {
- name: 'name',
- type: 'string',
- },
- ],
- Test: [
- {
- name: 'testAddress',
- type: 'address',
- },
- {
- name: 'testNumber',
- type: 'uint256',
- },
- ],
- },
- domain: {
- name: 'Test',
- },
- message: {
- testAddress: '0x0000000000000000000000000000000000000000',
- testNumber: '12345',
- },
- primaryType: 'Test',
- },
- EIP712_TEST_TYPED_DATA_HASH: '0xb460d69ca60383293877cd765c0f97bd832d66bca720f7e32222ce1118832493',
- EIP712_TEST_TYPED_DATA_SIGNED_RESULT:
- '0x20af5b6bfc3658942198d6eeda159b4ed589f90cee6eac3ba117818ffba5fd7e354a353aad93faabd6eb6c66e17921c92bd1cd09c92a770f554470dc3e254ce701',
-};
diff --git a/packages/subproviders/test/utils/ganache_subprovider.ts b/packages/subproviders/test/utils/ganache_subprovider.ts
deleted file mode 100644
index ac4a9325c..000000000
--- a/packages/subproviders/test/utils/ganache_subprovider.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import * as fs from 'fs';
-
-import { GanacheSubprovider } from '../../src/subproviders/ganache';
-import { configs } from '../utils/configs';
-
-const logger = {
- log: (arg: any) => {
- fs.appendFileSync('ganache.log', `${arg}\n`);
- },
-};
-
-export const ganacheSubprovider = new GanacheSubprovider({
- logger,
- verbose: false,
- port: configs.port,
- networkId: configs.networkId,
- mnemonic: configs.mnemonic,
-});
diff --git a/packages/subproviders/test/utils/report_callback_errors.ts b/packages/subproviders/test/utils/report_callback_errors.ts
deleted file mode 100644
index 6eb7420c3..000000000
--- a/packages/subproviders/test/utils/report_callback_errors.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { DoneCallback } from '@0x/types';
-
-export const reportCallbackErrors = (done: DoneCallback) => {
- return (f: (...args: any[]) => void) => {
- const wrapped = async (...args: any[]) => {
- try {
- f(...args);
- } catch (err) {
- done(err);
- }
- };
- return wrapped;
- };
-};
diff --git a/packages/subproviders/tsconfig.json b/packages/subproviders/tsconfig.json
deleted file mode 100644
index 2ee711adc..000000000
--- a/packages/subproviders/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "../../tsconfig",
- "compilerOptions": {
- "outDir": "lib",
- "rootDir": "."
- },
- "include": ["./src/**/*", "./test/**/*"]
-}
diff --git a/packages/subproviders/tslint.json b/packages/subproviders/tslint.json
deleted file mode 100644
index dd9053357..000000000
--- a/packages/subproviders/tslint.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": ["@0x/tslint-config"]
-}
diff --git a/packages/subproviders/typedoc-tsconfig.json b/packages/subproviders/typedoc-tsconfig.json
deleted file mode 100644
index c9b0af1ae..000000000
--- a/packages/subproviders/typedoc-tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../typedoc-tsconfig",
- "compilerOptions": {
- "outDir": "lib"
- },
- "include": ["./src/**/*", "./test/**/*"]
-}