aboutsummaryrefslogtreecommitdiffstats
path: root/packages/subproviders
diff options
context:
space:
mode:
Diffstat (limited to 'packages/subproviders')
-rw-r--r--packages/subproviders/CHANGELOG.md3
-rw-r--r--packages/subproviders/package.json2
-rw-r--r--packages/subproviders/src/globals.d.ts15
-rw-r--r--packages/subproviders/src/index.ts3
-rw-r--r--packages/subproviders/src/subproviders/empty_wallet_subprovider.ts17
-rw-r--r--packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts18
-rw-r--r--packages/subproviders/src/subproviders/ganache.ts28
-rw-r--r--packages/subproviders/src/subproviders/injected_web3.ts14
-rw-r--r--packages/subproviders/src/subproviders/ledger.ts4
-rw-r--r--packages/subproviders/src/subproviders/nonce_tracker.ts24
-rw-r--r--packages/subproviders/src/subproviders/redundant_rpc.ts7
-rw-r--r--packages/subproviders/src/subproviders/subprovider.ts12
-rw-r--r--packages/subproviders/src/types.ts9
-rw-r--r--packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts24
14 files changed, 117 insertions, 63 deletions
diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md
index 9ab7e6594..8c859f5a5 100644
--- a/packages/subproviders/CHANGELOG.md
+++ b/packages/subproviders/CHANGELOG.md
@@ -3,6 +3,9 @@
## v0.7.0 - _March 8, 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)
+ * Export `GanacheSubprovider` and `Subprovider` (#426)
+ * Make all subproviders to derive from `Subprovider` (#426)
+ * Add types for `NextCallback`, `OnNextCompleted` (#426)
## v0.6.0 - _March 4, 2018_
diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json
index c52484f82..259265a53 100644
--- a/packages/subproviders/package.json
+++ b/packages/subproviders/package.json
@@ -23,10 +23,12 @@
"@0xproject/utils": "^0.4.1",
"@ledgerhq/hw-app-eth": "^4.3.0",
"@ledgerhq/hw-transport-u2f": "^4.3.0",
+ "@0xproject/deployer": "^0.1.0",
"bn.js": "^4.11.8",
"es6-promisify": "^5.0.0",
"ethereumjs-tx": "^1.3.3",
"ethereumjs-util": "^5.1.1",
+ "ganache-core": "^2.0.2",
"hdkey": "^0.7.1",
"lodash": "^4.17.4",
"semaphore-async-await": "^1.5.1",
diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts
index d59ee9e67..fc0cdf038 100644
--- a/packages/subproviders/src/globals.d.ts
+++ b/packages/subproviders/src/globals.d.ts
@@ -134,3 +134,18 @@ declare module 'hdkey' {
}
export = HDNode;
}
+
+// hdkey declarations
+declare module 'ganache-core' {
+ import * as Web3 from 'web3';
+ export interface GanacheOpts {
+ verbose: boolean;
+ logger: {
+ log(msg: string): void;
+ };
+ port: number;
+ networkId: number;
+ mnemonic: string;
+ }
+ export function provider(opts: GanacheOpts): Web3.Provider;
+}
diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts
index e22b6f5f3..cafb50fe5 100644
--- a/packages/subproviders/src/index.ts
+++ b/packages/subproviders/src/index.ts
@@ -2,12 +2,15 @@ import Eth from '@ledgerhq/hw-app-eth';
import TransportU2F from '@ledgerhq/hw-transport-u2f';
import { LedgerEthereumClient } from './types';
+export { Callback, NextCallback } from './types';
export { EmptyWalletSubprovider } from './subproviders/empty_wallet_subprovider';
export { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_subprovider';
export { InjectedWeb3Subprovider } from './subproviders/injected_web3';
export { RedundantRPCSubprovider } from './subproviders/redundant_rpc';
export { LedgerSubprovider } from './subproviders/ledger';
+export { GanacheSubprovider } from './subproviders/ganache';
+export { Subprovider } from './subproviders/subprovider';
export { NonceTrackerSubprovider } from './subproviders/nonce_tracker';
export { ECSignature, LedgerWalletSubprovider, LedgerCommunicationClient, NonceSubproviderErrors } from './types';
diff --git a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
index 8c1fdfdb2..f5983dd9b 100644
--- a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
+++ b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
@@ -1,14 +1,20 @@
-import { JSONRPCPayload } from '@0xproject/types';
+import * as Web3 from 'web3';
+
+import { Subprovider } from './subprovider';
/*
* 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 {
+export class EmptyWalletSubprovider extends Subprovider {
// 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) {
+ public handleRequest(
+ payload: Web3.JSONRPCRequestPayload,
+ next: () => void,
+ end: (err: Error | null, result: any) => void,
+ ) {
switch (payload.method) {
case 'eth_accounts':
end(null, []);
@@ -19,9 +25,4 @@ export class EmptyWalletSubprovider {
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/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
index b455a0ed7..2421dcd02 100644
--- a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
+++ b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
@@ -1,4 +1,6 @@
-import { JSONRPCPayload } from '@0xproject/types';
+import * as Web3 from 'web3';
+
+import { Subprovider } from './subprovider';
/*
* This class implements the web3-provider-engine subprovider interface and returns
@@ -8,14 +10,19 @@ import { JSONRPCPayload } from '@0xproject/types';
* Source: https://github.com/trufflesuite/ganache-cli/issues/437
* Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
*/
-export class FakeGasEstimateSubprovider {
+export class FakeGasEstimateSubprovider extends Subprovider {
private _constantGasAmount: number;
constructor(constantGasAmount: number) {
+ super();
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) {
+ public handleRequest(
+ payload: Web3.JSONRPCRequestPayload,
+ next: () => void,
+ end: (err: Error | null, result: any) => void,
+ ) {
switch (payload.method) {
case 'eth_estimateGas':
end(null, this._constantGasAmount);
@@ -26,9 +33,4 @@ export class FakeGasEstimateSubprovider {
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/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts
new file mode 100644
index 000000000..a979aecf4
--- /dev/null
+++ b/packages/subproviders/src/subproviders/ganache.ts
@@ -0,0 +1,28 @@
+import * as Ganache from 'ganache-core';
+import * as Web3 from 'web3';
+
+import { Subprovider } from './subprovider';
+
+/*
+ * This class implements the web3-provider-engine subprovider interface and returns
+ * the provider connected to a in-process ganache.
+ * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
+ */
+export class GanacheSubprovider extends Subprovider {
+ private _ganacheProvider: Web3.Provider;
+ constructor(opts: any) {
+ super();
+ this._ganacheProvider = Ganache.provider(opts);
+ }
+ // 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: Web3.JSONRPCRequestPayload,
+ next: () => void,
+ end: (err: Error | null, result: any) => void,
+ ) {
+ this._ganacheProvider.sendAsync(payload, (err: Error | null, result: any) => {
+ end(err, result && result.result);
+ });
+ }
+}
diff --git a/packages/subproviders/src/subproviders/injected_web3.ts b/packages/subproviders/src/subproviders/injected_web3.ts
index 0d70180c4..6d4e2b27b 100644
--- a/packages/subproviders/src/subproviders/injected_web3.ts
+++ b/packages/subproviders/src/subproviders/injected_web3.ts
@@ -1,5 +1,7 @@
import * as _ from 'lodash';
-import Web3 = require('web3');
+import * as Web3 from 'web3';
+
+import { Subprovider } from './subprovider';
/*
* This class implements the web3-provider-engine subprovider interface and forwards
@@ -7,9 +9,10 @@ import Web3 = require('web3');
* provider instance in their browser.
* Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
*/
-export class InjectedWeb3Subprovider {
+export class InjectedWeb3Subprovider extends Subprovider {
private _injectedWeb3: Web3;
constructor(subprovider: Web3.Provider) {
+ super();
this._injectedWeb3 = new Web3(subprovider);
}
public handleRequest(
@@ -40,11 +43,4 @@ export class InjectedWeb3Subprovider {
return;
}
}
- // Required to implement this method despite not needing it for this subprovider
- // The engine argument type should be Web3ProviderEngine, but we've decided to keep it as type any
- // to remove the provider engine depdency given this method is a noop
- // tslint:disable-next-line:prefer-function-over-method
- public setEngine(engine: any) {
- // noop
- }
}
diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts
index 0a84caae3..03f7ef493 100644
--- a/packages/subproviders/src/subproviders/ledger.ts
+++ b/packages/subproviders/src/subproviders/ledger.ts
@@ -5,7 +5,7 @@ import ethUtil = require('ethereumjs-util');
import HDNode = require('hdkey');
import * as _ from 'lodash';
import Semaphore from 'semaphore-async-await';
-import Web3 = require('web3');
+import * as Web3 from 'web3';
import {
LedgerEthereumClient,
@@ -147,7 +147,7 @@ export class LedgerSubprovider extends Subprovider {
hdKey.publicKey = new Buffer(ledgerResponse.publicKey, 'hex');
hdKey.chainCode = new Buffer(ledgerResponse.chainCode, 'hex');
- const accounts = [];
+ const accounts: string[] = [];
for (let i = 0; i < numberOfAccounts; i++) {
const derivedHDNode = hdKey.derive(`m/${i + this._derivationPathIndex}`);
const derivedPublicKey = derivedHDNode.publicKey;
diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts
index d967d40f2..82eab4a9a 100644
--- a/packages/subproviders/src/subproviders/nonce_tracker.ts
+++ b/packages/subproviders/src/subproviders/nonce_tracker.ts
@@ -1,12 +1,12 @@
import * as _ from 'lodash';
+import { BlockParamLiteral } from '@0xproject/types';
import EthereumTx = require('ethereumjs-tx');
import ethUtil = require('ethereumjs-util');
+import * as Web3 from 'web3';
import providerEngineUtils = require('web3-provider-engine/util/rpc-cache-utils');
-import { BlockParamLiteral } from '@0xproject/types';
-
-import { ErrorCallback, JSONRPCPayload, NonceSubproviderErrors, OptionalNextCallback } from '../types';
+import { Callback, ErrorCallback, NextCallback, NonceSubproviderErrors } from '../types';
import { Subprovider } from './subprovider';
@@ -19,7 +19,7 @@ const NONCE_TOO_LOW_ERROR_MESSAGE = 'Transaction nonce is too low';
*/
export class NonceTrackerSubprovider extends Subprovider {
private _nonceCache: { [address: string]: string } = {};
- private static _reconstructTransaction(payload: JSONRPCPayload): EthereumTx {
+ private static _reconstructTransaction(payload: Web3.JSONRPCRequestPayload): EthereumTx {
const raw = payload.params[0];
if (_.isUndefined(raw)) {
throw new Error(NonceSubproviderErrors.EmptyParametersFound);
@@ -28,7 +28,7 @@ export class NonceTrackerSubprovider extends Subprovider {
const transaction = new EthereumTx(rawData);
return transaction;
}
- private static _determineAddress(payload: JSONRPCPayload): string {
+ private static _determineAddress(payload: Web3.JSONRPCRequestPayload): string {
let address: string;
switch (payload.method) {
case 'eth_getTransactionCount':
@@ -48,7 +48,11 @@ export class NonceTrackerSubprovider extends Subprovider {
}
// Required to implement this public interface which doesn't conform to our linting rule.
// tslint:disable-next-line:async-suffix
- public async handleRequest(payload: JSONRPCPayload, next: OptionalNextCallback, end: ErrorCallback): Promise<void> {
+ public async handleRequest(
+ payload: Web3.JSONRPCRequestPayload,
+ next: NextCallback,
+ end: ErrorCallback,
+ ): Promise<void> {
switch (payload.method) {
case 'eth_getTransactionCount':
const requestDefaultBlock = providerEngineUtils.blockTagForPayload(payload);
@@ -58,7 +62,7 @@ export class NonceTrackerSubprovider extends Subprovider {
if (!_.isUndefined(cachedResult)) {
return end(null, cachedResult);
} else {
- return next((requestError: Error | null, requestResult: any, cb: any) => {
+ return next((requestError: Error | null, requestResult: any, cb: Callback) => {
if (_.isNull(requestError)) {
this._nonceCache[address] = requestResult as string;
}
@@ -69,7 +73,7 @@ export class NonceTrackerSubprovider extends Subprovider {
return next();
}
case 'eth_sendRawTransaction':
- return next((sendTransactionError: Error | null, txResult: any, cb: any) => {
+ return next((sendTransactionError: Error | null, txResult: any, cb: Callback) => {
if (_.isNull(sendTransactionError)) {
this._handleSuccessfulTransaction(payload);
} else {
@@ -81,7 +85,7 @@ export class NonceTrackerSubprovider extends Subprovider {
return next();
}
}
- private _handleSuccessfulTransaction(payload: JSONRPCPayload): void {
+ private _handleSuccessfulTransaction(payload: Web3.JSONRPCRequestPayload): void {
const address = NonceTrackerSubprovider._determineAddress(payload);
const transaction = NonceTrackerSubprovider._reconstructTransaction(payload);
// Increment the nonce from the previous successfully submitted transaction
@@ -94,7 +98,7 @@ export class NonceTrackerSubprovider extends Subprovider {
const nextPrefixedHexNonce = `0x${nextHexNonce}`;
this._nonceCache[address] = nextPrefixedHexNonce;
}
- private _handleSendTransactionError(payload: JSONRPCPayload, err: Error): void {
+ private _handleSendTransactionError(payload: Web3.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/redundant_rpc.ts b/packages/subproviders/src/subproviders/redundant_rpc.ts
index 5a94f93d7..0df2f91f4 100644
--- a/packages/subproviders/src/subproviders/redundant_rpc.ts
+++ b/packages/subproviders/src/subproviders/redundant_rpc.ts
@@ -1,16 +1,15 @@
import { promisify } from '@0xproject/utils';
import * as _ from 'lodash';
+import * as Web3 from 'web3';
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
-import { JSONRPCPayload } from '../types';
-
import { Subprovider } from './subprovider';
export class RedundantRPCSubprovider extends Subprovider {
private _rpcs: RpcSubprovider[];
private static async _firstSuccessAsync(
rpcs: RpcSubprovider[],
- payload: JSONRPCPayload,
+ payload: Web3.JSONRPCRequestPayload,
next: () => void,
): Promise<any> {
let lastErr: Error | undefined;
@@ -38,7 +37,7 @@ export class RedundantRPCSubprovider extends Subprovider {
// Required to implement this public interface which doesn't conform to our linting rule.
// tslint:disable-next-line:async-suffix
public async handleRequest(
- payload: JSONRPCPayload,
+ payload: Web3.JSONRPCRequestPayload,
next: () => void,
end: (err: Error | null, data?: any) => void,
): Promise<void> {
diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts
index 6435c9f65..d4e0de67a 100644
--- a/packages/subproviders/src/subproviders/subprovider.ts
+++ b/packages/subproviders/src/subproviders/subprovider.ts
@@ -1,7 +1,5 @@
import promisify = require('es6-promisify');
-import Web3 = require('web3');
-
-import { JSONRPCPayload } from '../types';
+import * as Web3 from 'web3';
/*
* A version of the base class Subprovider found in providerEngine
* This one has an async/await `emitPayloadAsync` and also defined types.
@@ -19,7 +17,9 @@ export class Subprovider {
// 16 digits
return datePart + extraPart;
}
- private static _createFinalPayload(payload: JSONRPCPayload): Web3.JSONRPCRequestPayload {
+ private static _createFinalPayload(
+ payload: Partial<Web3.JSONRPCRequestPayload> & { method: string },
+ ): Web3.JSONRPCRequestPayload {
const finalPayload = {
// defaults
id: Subprovider._getRandomId(),
@@ -32,7 +32,9 @@ export class Subprovider {
public setEngine(engine: any): void {
this._engine = engine;
}
- public async emitPayloadAsync(payload: JSONRPCPayload): Promise<any> {
+ public async emitPayloadAsync(
+ payload: Partial<Web3.JSONRPCRequestPayload> & { method: string },
+ ): Promise<Web3.JSONRPCResponsePayload> {
const finalPayload = Subprovider._createFinalPayload(payload);
const response = await promisify(this._engine.sendAsync, this._engine)(finalPayload);
return response;
diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts
index f49ac6107..543da5947 100644
--- a/packages/subproviders/src/types.ts
+++ b/packages/subproviders/src/types.ts
@@ -91,11 +91,6 @@ export interface PartialTxParams {
export type DoneCallback = (err?: Error) => void;
-export interface JSONRPCPayload {
- params: any[];
- method: string;
-}
-
export interface LedgerCommunication {
close_async: () => Promise<void>;
}
@@ -118,5 +113,7 @@ export enum NonceSubproviderErrors {
CannotDetermineAddressFromPayload = 'CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD',
}
-export type OptionalNextCallback = (callback?: (err: Error | null, result: any, cb: any) => void) => void;
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;
diff --git a/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts b/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts
index e98d9023c..14176c145 100644
--- a/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts
+++ b/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts
@@ -1,9 +1,11 @@
import * as chai from 'chai';
+import * as fs from 'fs';
import * as _ from 'lodash';
+import * as path from 'path';
import Web3ProviderEngine = require('web3-provider-engine');
import FixtureSubprovider = require('web3-provider-engine/subproviders/fixture');
-import promisify = require('es6-promisify');
+import { promisify } from '@0xproject/utils';
import EthereumTx = require('ethereumjs-tx');
import { NonceTrackerSubprovider } from '../../src';
@@ -62,9 +64,9 @@ describe('NonceTrackerSubprovider', () => {
const payload = { ...getTransactionCountPayload, params: ['0x0', 'pending'] };
- const response = await promisify(provider.sendAsync, provider)(payload);
+ const response = await promisify<any>(provider.sendAsync, provider)(payload);
expect(response.result).to.be.eq('0x00');
- const secondResponse = await promisify(provider.sendAsync, provider)(payload);
+ const secondResponse = await promisify<any>(provider.sendAsync, provider)(payload);
expect(secondResponse.result).to.be.eq('0x00');
});
it('does not cache the result for latest transaction count', async () => {
@@ -76,9 +78,9 @@ describe('NonceTrackerSubprovider', () => {
const payload = { ...getTransactionCountPayload, params: ['0x0', 'latest'] };
- const response = await promisify(provider.sendAsync, provider)(payload);
+ const response = await promisify<any>(provider.sendAsync, provider)(payload);
expect(response.result).to.be.eq('0x00');
- const secondResponse = await promisify(provider.sendAsync, provider)(payload);
+ const secondResponse = await promisify<any>(provider.sendAsync, provider)(payload);
expect(secondResponse.result).to.be.eq('0x99');
});
it('clears the cache on a Nonce Too Low Error', async () => {
@@ -105,14 +107,14 @@ describe('NonceTrackerSubprovider', () => {
params: [transaction.serialize()],
};
- const response = await promisify(provider.sendAsync, provider)(noncePayload);
+ const response = await promisify<any>(provider.sendAsync, provider)(noncePayload);
expect(response.result).to.be.eq('0x00');
- const secondResponse = await promisify(provider.sendAsync, provider)(noncePayload);
+ const secondResponse = await promisify<any>(provider.sendAsync, provider)(noncePayload);
expect(secondResponse.result).to.be.eq('0x00');
try {
await promisify(provider.sendAsync, provider)(txPayload);
} catch (err) {
- const thirdResponse = await promisify(provider.sendAsync, provider)(noncePayload);
+ const thirdResponse = await promisify<any>(provider.sendAsync, provider)(noncePayload);
expect(thirdResponse.result).to.be.eq('0x99');
}
});
@@ -140,12 +142,12 @@ describe('NonceTrackerSubprovider', () => {
params: [transaction.serialize()],
};
- const response = await promisify(provider.sendAsync, provider)(noncePayload);
+ const response = await promisify<any>(provider.sendAsync, provider)(noncePayload);
expect(response.result).to.be.eq('0x00');
- const secondResponse = await promisify(provider.sendAsync, provider)(noncePayload);
+ const secondResponse = await promisify<any>(provider.sendAsync, provider)(noncePayload);
expect(secondResponse.result).to.be.eq('0x00');
await promisify(provider.sendAsync, provider)(txPayload);
- const thirdResponse = await promisify(provider.sendAsync, provider)(noncePayload);
+ const thirdResponse = await promisify<any>(provider.sendAsync, provider)(noncePayload);
expect(thirdResponse.result).to.be.eq('0x01');
});
});