From 709026bf1a49d468850b4ebed845c8598fa4fd75 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 19 Jan 2018 15:34:28 +0100 Subject: Refactor contracts tests to not use injected web3 instance --- packages/dev-utils/package.json | 5 ++- packages/dev-utils/src/constants.ts | 4 +++ packages/dev-utils/src/globals.d.ts | 2 ++ packages/dev-utils/src/index.ts | 2 ++ .../src/subproviders/empty_wallet_subprovider.ts | 27 ++++++++++++++ .../subproviders/fake_gas_estimate_subprovider.ts | 34 ++++++++++++++++++ packages/dev-utils/src/web3_factory.ts | 42 ++++++++++++++++++++++ packages/dev-utils/tsconfig.json | 1 + 8 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 packages/dev-utils/src/constants.ts create mode 100644 packages/dev-utils/src/globals.d.ts create mode 100644 packages/dev-utils/src/subproviders/empty_wallet_subprovider.ts create mode 100644 packages/dev-utils/src/subproviders/fake_gas_estimate_subprovider.ts create mode 100644 packages/dev-utils/src/web3_factory.ts (limited to 'packages/dev-utils') diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index bd77b7c20..96f21ec17 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -21,6 +21,7 @@ "devDependencies": { "@0xproject/tslint-config": "^0.4.5", "@types/lodash": "^4.14.86", + "@0xproject/types": "^0.1.4", "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.8.0", @@ -32,6 +33,8 @@ "@0xproject/utils": "^0.2.3", "ethereumjs-util": "^5.1.2", "lodash": "^4.17.4", - "request-promise-native": "^1.0.5" + "request-promise-native": "^1.0.5", + "web3": "^0.20.0", + "web3-provider-engine": "^13.0.1" } } diff --git a/packages/dev-utils/src/constants.ts b/packages/dev-utils/src/constants.ts new file mode 100644 index 000000000..14cb5b937 --- /dev/null +++ b/packages/dev-utils/src/constants.ts @@ -0,0 +1,4 @@ +export const constants = { + RPC_URL: 'http://localhost:8545', + GAS_ESTIMATE: 500000, +}; diff --git a/packages/dev-utils/src/globals.d.ts b/packages/dev-utils/src/globals.d.ts new file mode 100644 index 000000000..7b132ee28 --- /dev/null +++ b/packages/dev-utils/src/globals.d.ts @@ -0,0 +1,2 @@ +declare module 'web3-provider-engine'; +declare module 'web3-provider-engine/subproviders/rpc'; diff --git a/packages/dev-utils/src/index.ts b/packages/dev-utils/src/index.ts index 9ba0cb5cf..e899ac206 100644 --- a/packages/dev-utils/src/index.ts +++ b/packages/dev-utils/src/index.ts @@ -1,2 +1,4 @@ export { RPC } from './rpc'; export { BlockchainLifecycle } from './blockchain_lifecycle'; +export { web3Factory } from './web3_factory'; +export { constants as devConstants } from './constants'; diff --git a/packages/dev-utils/src/subproviders/empty_wallet_subprovider.ts b/packages/dev-utils/src/subproviders/empty_wallet_subprovider.ts new file mode 100644 index 000000000..8c1fdfdb2 --- /dev/null +++ b/packages/dev-utils/src/subproviders/empty_wallet_subprovider.ts @@ -0,0 +1,27 @@ +import { JSONRPCPayload } from '@0xproject/types'; + +/* + * This class implements the web3-provider-engine subprovider interface and returns + * that the provider has no addresses when queried. + * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js + */ +export class EmptyWalletSubprovider { + // This method needs to be here to satisfy the interface but linter wants it to be static. + // tslint:disable-next-line:prefer-function-over-method + public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error | null, result: any) => void) { + switch (payload.method) { + case 'eth_accounts': + end(null, []); + return; + + default: + next(); + return; + } + } + // Required to implement this method despite not needing it for this subprovider + // tslint:disable-next-line:prefer-function-over-method + public setEngine(engine: any) { + // noop + } +} diff --git a/packages/dev-utils/src/subproviders/fake_gas_estimate_subprovider.ts b/packages/dev-utils/src/subproviders/fake_gas_estimate_subprovider.ts new file mode 100644 index 000000000..b455a0ed7 --- /dev/null +++ b/packages/dev-utils/src/subproviders/fake_gas_estimate_subprovider.ts @@ -0,0 +1,34 @@ +import { JSONRPCPayload } from '@0xproject/types'; + +/* + * This class implements the web3-provider-engine subprovider interface and returns + * the constant gas estimate when queried. + * 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 + */ +export class FakeGasEstimateSubprovider { + private _constantGasAmount: number; + constructor(constantGasAmount: number) { + this._constantGasAmount = constantGasAmount; + } + // This method needs to be here to satisfy the interface but linter wants it to be static. + // tslint:disable-next-line:prefer-function-over-method + public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error | null, result: any) => void) { + switch (payload.method) { + case 'eth_estimateGas': + end(null, this._constantGasAmount); + return; + + default: + next(); + return; + } + } + // Required to implement this method despite not needing it for this subprovider + // tslint:disable-next-line:prefer-function-over-method + public setEngine(engine: any) { + // noop + } +} diff --git a/packages/dev-utils/src/web3_factory.ts b/packages/dev-utils/src/web3_factory.ts new file mode 100644 index 000000000..26c26e03d --- /dev/null +++ b/packages/dev-utils/src/web3_factory.ts @@ -0,0 +1,42 @@ +// HACK: web3 injects XMLHttpRequest into the global scope and ProviderEngine checks XMLHttpRequest +// to know whether it is running in a browser or node environment. We need it to be undefined since +// we are not running in a browser env. +// Filed issue: https://github.com/ethereum/web3.js/issues/844 +(global as any).XMLHttpRequest = undefined; +import ProviderEngine = require('web3-provider-engine'); +import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); + +import { EmptyWalletSubprovider } from './subproviders/empty_wallet_subprovider'; +import { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_subprovider'; + +import { constants } from './constants'; + +// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang +// because they are using the wrong XHR package. +// importing web3 after subproviders fixes this issue +// Filed issue: https://github.com/ethereum/web3.js/issues/844 +// tslint:disable-next-line:ordered-imports +import * as Web3 from 'web3'; + +export const web3Factory = { + create(hasAddresses: boolean = true): Web3 { + const provider = this.getRpcProvider(hasAddresses); + const web3 = new Web3(); + web3.setProvider(provider); + return web3; + }, + getRpcProvider(hasAddresses: boolean = true): Web3.Provider { + const provider = new ProviderEngine(); + if (!hasAddresses) { + provider.addProvider(new EmptyWalletSubprovider()); + } + provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_ESTIMATE)); + provider.addProvider( + new RpcSubprovider({ + rpcUrl: constants.RPC_URL, + }), + ); + provider.start(); + return provider; + }, +}; diff --git a/packages/dev-utils/tsconfig.json b/packages/dev-utils/tsconfig.json index b28e45170..bdf315d59 100644 --- a/packages/dev-utils/tsconfig.json +++ b/packages/dev-utils/tsconfig.json @@ -6,6 +6,7 @@ "include": [ "./src/**/*", "../../node_modules/types-bn/index.d.ts", + "../../node_modules/web3-typescript-typings/index.d.ts", "../../node_modules/types-ethereumjs-util/index.d.ts" ] } -- cgit v1.2.3