diff --git a/packages/assert/src/index.ts b/packages/assert/src/index.ts index 741bd78e16..0f05e3bd0b 100644 --- a/packages/assert/src/index.ts +++ b/packages/assert/src/index.ts @@ -59,10 +59,6 @@ export const assert = { isBoolean(variableName: string, value: boolean): void { assert.assert(_.isBoolean(value), assert.typeAssertionMessage(variableName, 'boolean', value)); }, - isWeb3Provider(variableName: string, value: any): void { - const isWeb3Provider = _.isFunction(value.send) || _.isFunction(value.sendAsync); - assert.assert(isWeb3Provider, assert.typeAssertionMessage(variableName, 'Provider', value)); - }, doesConformToSchema(variableName: string, value: any, schema: Schema, subSchemas?: Schema[]): void { if (_.isUndefined(value)) { throw new Error(`${variableName} can't be undefined`); diff --git a/packages/assert/test/assert_test.ts b/packages/assert/test/assert_test.ts index 9266496ac0..4f67871032 100644 --- a/packages/assert/test/assert_test.ts +++ b/packages/assert/test/assert_test.ts @@ -154,18 +154,6 @@ describe('Assertions', () => { invalidInputs.forEach(input => expect(assert.isBoolean.bind(assert, variableName, input)).to.throw()); }); }); - describe('#isWeb3Provider', () => { - it('should not throw for valid input', () => { - const validInputs = [{ send: () => 45 }, { sendAsync: () => 45 }]; - validInputs.forEach(input => - expect(assert.isWeb3Provider.bind(assert, variableName, input)).to.not.throw(), - ); - }); - it('should throw for invalid input', () => { - const invalidInputs = [42, { random: 'test' }, undefined, new BigNumber(45)]; - invalidInputs.forEach(input => expect(assert.isWeb3Provider.bind(assert, variableName, input)).to.throw()); - }); - }); describe('#doesConformToSchema', () => { const schema = schemas.addressSchema; it('should not throw for valid input', () => { diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index b22b1a122d..88972690a5 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -2,7 +2,7 @@ import { ContractWrappers, ContractWrappersError, ForwarderWrapperError } from ' import { schemas } from '@0x/json-schemas'; import { SignedOrder } from '@0x/order-utils'; import { ObjectMap } from '@0x/types'; -import { BigNumber } from '@0x/utils'; +import { BigNumber, providerUtils } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider } from 'ethereum-types'; import * as _ from 'lodash'; @@ -56,7 +56,7 @@ export class AssetBuyer { orders: SignedOrder[], options: Partial = {}, ): AssetBuyer { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema); assert.assert(orders.length !== 0, `Expected orders to contain at least one order`); const orderProvider = new BasicOrderProvider(orders); @@ -76,7 +76,7 @@ export class AssetBuyer { sraApiUrl: string, options: Partial = {}, ): AssetBuyer { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isWebUri('sraApiUrl', sraApiUrl); const networkId = options.networkId || constants.DEFAULT_ASSET_BUYER_OPTS.networkId; const orderProvider = new StandardRelayerAPIOrderProvider(sraApiUrl, networkId); @@ -97,7 +97,7 @@ export class AssetBuyer { constants.DEFAULT_ASSET_BUYER_OPTS, options, ); - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isValidOrderProvider('orderProvider', orderProvider); assert.isNumber('networkId', networkId); assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs); diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index 0238106f32..f6f5a4fc17 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -1,4 +1,4 @@ -import { AbiEncoder, abiUtils, BigNumber } from '@0x/utils'; +import { AbiEncoder, abiUtils, BigNumber, providerUtils } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { AbiDefinition, @@ -157,8 +157,9 @@ export class BaseContract { provider: Provider, txDefaults?: Partial, ) { + const web3WrapperProvider = providerUtils.standardizeOrThrow(provider); this.contractName = contractName; - this._web3Wrapper = new Web3Wrapper(provider, txDefaults); + this._web3Wrapper = new Web3Wrapper(web3WrapperProvider, txDefaults); this.abi = abi; this.address = address; const methodAbis = this.abi.filter( diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts index f43dc5d265..770887c033 100644 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -9,7 +9,7 @@ import { OrderValidator, WETH9, } from '@0x/contract-artifacts'; -import { AbiDecoder } from '@0x/utils'; +import { AbiDecoder, providerUtils } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider } from 'ethereum-types'; import * as _ from 'lodash'; @@ -82,7 +82,7 @@ export class ContractWrappers { * @return An instance of the ContractWrappers class. */ constructor(provider: Provider, config: ContractWrappersConfig) { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.doesConformToSchema('config', config, ContractWrappersConfigSchema); const txDefaults = { gasPrice: config.gasPrice, diff --git a/packages/ethereum-types/src/index.ts b/packages/ethereum-types/src/index.ts index 8339ab5a67..d98245136c 100644 --- a/packages/ethereum-types/src/index.ts +++ b/packages/ethereum-types/src/index.ts @@ -6,10 +6,61 @@ export type JSONRPCErrorCallback = (err: Error | null, result?: JSONRPCResponseP * Do not create your own provider. Use an existing provider from a Web3 or ProviderEngine library * Read more about Providers in the 0x wiki. */ -export interface Provider { +export type Provider = Web3JsProvider | Web3WrapperProvider | EIP1193Provider; + +export type Web3JsProvider = Web3JsV1Provider | Web3JsV2Provider | Web3JsV3Provider; + +/** + * Web3.js version 3 provider interface + * This provider interface was implemented with the hopes for conforming to the EIP1193 spec, + * however it does not conform entirely. + */ +export interface Web3JsV3Provider { + send(method: string, params?: any[]): Promise; +} + +/** + * The interface for the provider used by @0x/web3-wrapper + */ +export interface Web3WrapperProvider { sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): void; } +export type GanacheProvider = Web3WrapperProvider; +export type ProviderEngineProvider = Web3WrapperProvider; + +/** + * Web3.js version 1 provider interface + * This provider interface was implemented in the pre-1.0Beta releases for Web3.js. + * This interface allowed sending synchonous requests, support for which was later dropped. + */ +export interface Web3JsV1Provider { + sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): void; + send(payload: JSONRPCRequestPayload): JSONRPCResponsePayload; +} + +/** + * Web3.js version 2 provider interface + * This provider interface was used in a couple of Web3.js 1.0 beta releases + * before the first attempts to conform to EIP1193 + */ +export interface Web3JsV2Provider { + send(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): void; +} + +/** + * Interface for providers that conform to EIP 1193 + * Source: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md + */ + +export type EIP1193Event = 'accountsChanged' | 'networkChanged' | 'close' | 'connect' | 'notification'; + +export interface EIP1193Provider { + isEIP1193: boolean; + send(method: string, params?: any[]): Promise; + on(event: EIP1193Event, listener: (result: any) => void): this; +} + export type ContractAbi = AbiDefinition[]; export type AbiDefinition = FunctionAbi | EventAbi; diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 243bb569b8..e15bea18e8 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -1,5 +1,6 @@ import { AssetBuyer, BigNumber } from '@0x/asset-buyer'; import { assetDataUtils } from '@0x/order-utils'; +import { providerUtils } from '@0x/utils'; import { Provider } from 'ethereum-types'; import * as _ from 'lodash'; import * as React from 'react'; @@ -50,7 +51,7 @@ const validateInstantRenderConfig = (config: ZeroExInstantConfig, selector: stri assert.isValidAffiliateInfo('affiliateInfo', config.affiliateInfo); } if (!_.isUndefined(config.provider)) { - assert.isWeb3Provider('provider', config.provider); + providerUtils.standardizeOrThrow(config.provider); } if (!_.isUndefined(config.walletDisplayName)) { assert.isString('walletDisplayName', config.walletDisplayName); @@ -158,7 +159,7 @@ export const hasLiquidityForAssetDataAsync = async ( assert.isNumber('networkId', networkId); if (provider !== undefined) { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); } const bestProvider: Provider = provider || providerFactory.getFallbackNoSigningProvider(networkId); diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts index efcc146bf8..7a9effa577 100644 --- a/packages/order-utils/src/signature_utils.ts +++ b/packages/order-utils/src/signature_utils.ts @@ -3,6 +3,7 @@ import { getContractAddressesForNetworkOrThrow } from '@0x/contract-addresses'; import * as artifacts from '@0x/contract-artifacts'; import { schemas } from '@0x/json-schemas'; import { ECSignature, Order, SignatureType, SignedOrder, ValidatorSignature } from '@0x/types'; +import { providerUtils } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; @@ -29,7 +30,7 @@ export const signatureUtils = { signature: string, signerAddress: string, ): Promise { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isHexString('data', data); assert.isHexString('signature', signature); assert.isETHAddressHex('signerAddress', signerAddress); @@ -90,7 +91,7 @@ export const signatureUtils = { * @return Whether the data was preSigned by the supplied signerAddress */ async isValidPresignedSignatureAsync(provider: Provider, data: string, signerAddress: string): Promise { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isHexString('data', data); assert.isETHAddressHex('signerAddress', signerAddress); const web3Wrapper = new Web3Wrapper(provider); @@ -118,7 +119,7 @@ export const signatureUtils = { signature: string, signerAddress: string, ): Promise { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isHexString('data', data); assert.isHexString('signature', signature); assert.isETHAddressHex('signerAddress', signerAddress); @@ -142,7 +143,7 @@ export const signatureUtils = { signature: string, signerAddress: string, ): Promise { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isHexString('data', data); assert.isHexString('signature', signature); assert.isETHAddressHex('signerAddress', signerAddress); @@ -238,7 +239,7 @@ export const signatureUtils = { * @return A SignedOrder containing the order and Elliptic curve signature with Signature Type. */ async ecSignTypedDataOrderAsync(provider: Provider, order: Order, signerAddress: string): Promise { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isETHAddressHex('signerAddress', signerAddress); assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]); const web3Wrapper = new Web3Wrapper(provider); @@ -276,7 +277,7 @@ export const signatureUtils = { * @return A hex encoded string containing the Elliptic curve signature generated by signing the msgHash and the Signature Type. */ async ecSignHashAsync(provider: Provider, msgHash: string, signerAddress: string): Promise { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isHexString('msgHash', msgHash); assert.isETHAddressHex('signerAddress', signerAddress); const web3Wrapper = new Web3Wrapper(provider); diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index a06fd0cfeb..f9c1435e1d 100644 --- a/packages/order-watcher/src/order_watcher/order_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -33,7 +33,7 @@ import { OrderStateUtils, } from '@0x/order-utils'; import { AssetProxyId, ExchangeContractErrs, OrderState, SignedOrder, Stats } from '@0x/types'; -import { errorUtils, intervalUtils } from '@0x/utils'; +import { errorUtils, intervalUtils, providerUtils } from '@0x/utils'; import { BlockParamLiteral, LogEntryEvent, LogWithDecodedArgs, Provider } from 'ethereum-types'; import * as _ from 'lodash'; @@ -102,7 +102,7 @@ export class OrderWatcher { contractAddresses?: ContractAddresses, partialConfig: Partial = DEFAULT_ORDER_WATCHER_CONFIG, ) { - assert.isWeb3Provider('provider', provider); + providerUtils.standardizeOrThrow(provider); assert.isNumber('networkId', networkId); assert.doesConformToSchema('partialConfig', partialConfig, orderWatcherPartialConfigSchema); const config = { diff --git a/packages/sol-tracing-utils/src/trace_collection_subprovider.ts b/packages/sol-tracing-utils/src/trace_collection_subprovider.ts index 7fde1f9b8f..76164bd917 100644 --- a/packages/sol-tracing-utils/src/trace_collection_subprovider.ts +++ b/packages/sol-tracing-utils/src/trace_collection_subprovider.ts @@ -2,7 +2,7 @@ import { BlockchainLifecycle } from '@0x/dev-utils'; import { Callback, ErrorCallback, NextCallback, Subprovider } from '@0x/subproviders'; import { logUtils } from '@0x/utils'; import { CallDataRPC, marshaller, Web3Wrapper } from '@0x/web3-wrapper'; -import { JSONRPCRequestPayload, Provider, TxData } from 'ethereum-types'; +import { JSONRPCRequestPayload, ProviderEngineProvider, TxData } from 'ethereum-types'; import { utils } from 'ethers'; import * as _ from 'lodash'; import { Lock } from 'semaphore-async-await'; @@ -142,7 +142,7 @@ export abstract class TraceCollectionSubprovider extends Subprovider { * directly. * @param engine The ProviderEngine this subprovider is added to */ - public setEngine(engine: Provider): void { + public setEngine(engine: ProviderEngineProvider): void { super.setEngine(engine); this._web3Wrapper = new Web3Wrapper(engine); } diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 66a09000c1..588190268e 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -37,7 +37,6 @@ "@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", diff --git a/packages/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts index 2b8544f8b8..6e53eeecca 100644 --- a/packages/subproviders/src/subproviders/ganache.ts +++ b/packages/subproviders/src/subproviders/ganache.ts @@ -1,4 +1,4 @@ -import { JSONRPCRequestPayload, Provider } from 'ethereum-types'; +import { GanacheProvider, JSONRPCRequestPayload } from 'ethereum-types'; import * as Ganache from 'ganache-core'; import { Callback, ErrorCallback } from '../types'; @@ -10,7 +10,7 @@ import { Subprovider } from './subprovider'; * It intercepts all JSON RPC requests and relays them to an in-process ganache instance. */ export class GanacheSubprovider extends Subprovider { - private readonly _ganacheProvider: Provider; + private readonly _ganacheProvider: GanacheProvider; /** * Instantiates a GanacheSubprovider * @param opts The desired opts with which to instantiate the Ganache provider diff --git a/packages/subproviders/src/subproviders/metamask_subprovider.ts b/packages/subproviders/src/subproviders/metamask_subprovider.ts index ba207d4cce..a9d9117785 100644 --- a/packages/subproviders/src/subproviders/metamask_subprovider.ts +++ b/packages/subproviders/src/subproviders/metamask_subprovider.ts @@ -1,5 +1,6 @@ +import { providerUtils } from '@0x/utils'; import { marshaller, Web3Wrapper } from '@0x/web3-wrapper'; -import { JSONRPCRequestPayload, Provider } from 'ethereum-types'; +import { JSONRPCRequestPayload, Web3WrapperProvider } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import { Callback, ErrorCallback } from '../types'; @@ -16,15 +17,16 @@ import { Subprovider } from './subprovider'; */ export class MetamaskSubprovider extends Subprovider { private readonly _web3Wrapper: Web3Wrapper; - private readonly _provider: Provider; + private readonly _provider: Web3WrapperProvider; /** * Instantiates a new MetamaskSubprovider * @param provider Web3 provider that should handle all user account related requests */ - constructor(provider: Provider) { + constructor(provider: Web3WrapperProvider) { super(); this._web3Wrapper = new Web3Wrapper(provider); - this._provider = provider; + const web3WrapperProvider = providerUtils.standardizeOrThrow(provider); + this._provider = web3WrapperProvider; } /** * This method conforms to the web3-provider-engine interface. diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts index cd6780e0c8..d1112334c8 100644 --- a/packages/subproviders/src/subproviders/subprovider.ts +++ b/packages/subproviders/src/subproviders/subprovider.ts @@ -1,5 +1,5 @@ import { promisify } from '@0x/utils'; -import { JSONRPCRequestPayload, JSONRPCResponsePayload, Provider } from 'ethereum-types'; +import { JSONRPCRequestPayload, JSONRPCResponsePayload, ProviderEngineProvider } from 'ethereum-types'; import { Callback, ErrorCallback, JSONRPCRequestPayloadWithMethod } from '../types'; /** @@ -8,7 +8,7 @@ import { Callback, ErrorCallback, JSONRPCRequestPayloadWithMethod } from '../typ */ export abstract class Subprovider { // tslint:disable-next-line:underscore-private-and-protected - private engine!: Provider; + private engine!: ProviderEngineProvider; protected static _createFinalPayload( payload: Partial, ): Partial { @@ -64,7 +64,7 @@ export abstract class Subprovider { * directly. * @param engine The ProviderEngine this subprovider is added to */ - public setEngine(engine: Provider): void { + public setEngine(engine: ProviderEngineProvider): void { this.engine = engine; } } diff --git a/packages/typescript-typings/types/ganache-core/index.d.ts b/packages/typescript-typings/types/ganache-core/index.d.ts new file mode 100644 index 0000000000..58b059beac --- /dev/null +++ b/packages/typescript-typings/types/ganache-core/index.d.ts @@ -0,0 +1,16 @@ +declare module 'ganache-core' { + export interface GanacheOpts { + verbose?: boolean; + logger?: { + log(msg: string): void; + }; + port?: number; + network_id?: number; + networkId?: number; + mnemonic?: string; + gasLimit?: number; + vmErrorsOnRPCResponse?: boolean; + db_path?: string; + } + export function provider(opts: GanacheOpts): GanacheProvider; +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index f9c2693fe0..02d4c545e3 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -2,6 +2,7 @@ export { promisify } from './promisify'; export { addressUtils } from './address_utils'; export { classUtils } from './class_utils'; export { intervalUtils } from './interval_utils'; +export { providerUtils } from './provider_utils'; export { BigNumber } from './configured_bignumber'; export { AbiDecoder } from './abi_decoder'; export { logUtils } from './log_utils'; diff --git a/packages/utils/src/provider_utils.ts b/packages/utils/src/provider_utils.ts new file mode 100644 index 0000000000..ff928dd86e --- /dev/null +++ b/packages/utils/src/provider_utils.ts @@ -0,0 +1,63 @@ +import { + EIP1193Provider, + JSONRPCErrorCallback, + JSONRPCRequestPayload, + Provider, + Web3WrapperProvider, +} from 'ethereum-types'; +import * as _ from 'lodash'; + +export const providerUtils = { + standardizeOrThrow(provider: Provider): Web3WrapperProvider { + if ((provider as EIP1193Provider).isEIP1193) { + const web3WrapperProvider: Web3WrapperProvider = { + sendAsync: (payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback) => { + const method = payload.method; + const params = payload.params; + (provider as EIP1193Provider) + .send(method, params) + .then((result: any) => { + callback(null, result); + }) + .catch((err: Error) => { + callback(err); + }); + }, + }; + return web3WrapperProvider; + } else if (_.isUndefined((provider as any).sendAsync)) { + // Web3@1.0 provider doesn't support synchronous http requests, + // so it only has an async `send` method, instead of a `send` and `sendAsync` in web3@0.x.x` + // We re-assign the send method so that Web3@1.0 providers work with @0x/web3-wrapper + const web3WrapperProvider: Web3WrapperProvider = { + sendAsync: (provider as any).send, + }; + return web3WrapperProvider; + } else if (!_.isUndefined((provider as any).sendAsync)) { + return provider as Web3WrapperProvider; + } else if ((provider as any).host) { + // HACK(fabio): Web3 1.0 Beta modified their `send` method to comply with EIP1193 but did not add the + // `isEIP1193` flag. The only common identifier across Web3 providers is that they all have + // a `host` property, so we check for it's existence. We put this check last to make it less likely + // that this condition is hit for other providers that also expose a `host` property. + const web3WrapperProvider: Web3WrapperProvider = { + sendAsync: (payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback) => { + const method = payload.method; + const params = payload.params; + (provider as any) + .send(method, params) + .then((result: any) => { + callback(null, result); + }) + .catch((err: Error) => { + callback(err); + }); + }, + }; + return web3WrapperProvider; + } + throw new Error( + `Unsupported provider found. Please make sure it conforms to one of the supported providers. See 'Provider' type in 'ethereum-types' package.`, + ); + }, +}; diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index d6f0bf90d0..4919906e95 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -37,7 +37,6 @@ "homepage": "https://github.com/0xProject/0x-monorepo/packages/web3-wrapper/README.md", "devDependencies": { "@0x/tslint-config": "^3.0.0", - "@types/ganache-core": "^2.1.2", "@types/lodash": "4.14.104", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts index 76cae4b01a..c8b88d63dc 100644 --- a/packages/web3-wrapper/src/web3_wrapper.ts +++ b/packages/web3-wrapper/src/web3_wrapper.ts @@ -1,6 +1,6 @@ import { assert } from '@0x/assert'; import { schemas } from '@0x/json-schemas'; -import { AbiDecoder, addressUtils, BigNumber, intervalUtils, promisify } from '@0x/utils'; +import { AbiDecoder, addressUtils, BigNumber, intervalUtils, promisify, providerUtils } from '@0x/utils'; import { BlockParam, BlockParamLiteral, @@ -19,6 +19,7 @@ import { TransactionReceiptWithDecodedLogs, TransactionTrace, TxData, + Web3WrapperProvider, } from 'ethereum-types'; import * as _ from 'lodash'; @@ -51,7 +52,7 @@ export class Web3Wrapper { */ public isZeroExWeb3Wrapper = true; public abiDecoder: AbiDecoder; - private _provider: Provider; + private _provider: Web3WrapperProvider; private readonly _txDefaults: Partial; private _jsonRpcRequestId: number; /** @@ -148,15 +149,9 @@ export class Web3Wrapper { * @return An instance of the Web3Wrapper class. */ constructor(provider: Provider, txDefaults?: Partial) { - assert.isWeb3Provider('provider', provider); - if (_.isUndefined((provider as any).sendAsync)) { - // Web3@1.0 provider doesn't support synchronous http requests, - // so it only has an async `send` method, instead of a `send` and `sendAsync` in web3@0.x.x` - // We re-assign the send method so that Web3@1.0 providers work with @0x/web3-wrapper - (provider as any).sendAsync = (provider as any).send; - } + const web3WrapperProvider = providerUtils.standardizeOrThrow(provider); this.abiDecoder = new AbiDecoder([]); - this._provider = provider; + this._provider = web3WrapperProvider; this._txDefaults = txDefaults || {}; this._jsonRpcRequestId = 1; } @@ -179,8 +174,8 @@ export class Web3Wrapper { * @param provider The new Web3 provider to be set */ public setProvider(provider: Provider): void { - assert.isWeb3Provider('provider', provider); - this._provider = provider; + const web3WrapperProvider = providerUtils.standardizeOrThrow(provider); + this._provider = web3WrapperProvider; } /** * Check whether an address is available through the backing provider. This can be diff --git a/yarn.lock b/yarn.lock index b4aae4b0af..6f5ccc044b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -587,6 +587,19 @@ ethers "~4.0.4" lodash "^4.17.11" +"@0x/web3-wrapper@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-4.0.2.tgz#d4e0a4fa1217155e1aed4cd91086654fd99f2959" + dependencies: + "@0x/assert" "^2.0.2" + "@0x/json-schemas" "^3.0.2" + "@0x/typescript-typings" "^4.0.0" + "@0x/utils" "^4.0.3" + ethereum-types "^2.0.0" + ethereumjs-util "^5.1.1" + ethers "~4.0.4" + lodash "^4.17.11" + "@0xproject/npm-cli-login@^0.0.11": version "0.0.11" resolved "https://registry.yarnpkg.com/@0xproject/npm-cli-login/-/npm-cli-login-0.0.11.tgz#3f1ec06112ce62aad300ff0575358f68aeecde2e" @@ -1453,12 +1466,6 @@ dependencies: "@types/node" "*" -"@types/ganache-core@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@types/ganache-core/-/ganache-core-2.1.2.tgz#e4db6ce901da03be4d2a66de34e06b1f9b90c5e8" - dependencies: - "@types/ethereum-protocol" "*" - "@types/glob@*", "@types/glob@5.0.35": version "5.0.35" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a" @@ -13518,6 +13525,8 @@ react-highlight@0xproject/react-highlight#react-peer-deps: dependencies: highlight.js "^9.11.0" highlightjs-solidity "^1.0.5" + react "^16.4.2" + react-dom "^16.4.2" react-hot-loader@^4.3.3: version "4.3.4"