aboutsummaryrefslogtreecommitdiffstats
path: root/packages/subproviders/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/subproviders/src')
-rw-r--r--packages/subproviders/src/globals.d.ts25
-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.ts36
-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
11 files changed, 114 insertions, 79 deletions
diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts
index e51801b5c..b3dcd4ed3 100644
--- a/packages/subproviders/src/globals.d.ts
+++ b/packages/subproviders/src/globals.d.ts
@@ -67,16 +67,6 @@ declare module '@ledgerhq/hw-transport-node-hid' {
}
}
-// Semaphore-async-await declarations
-declare module 'semaphore-async-await' {
- class Semaphore {
- constructor(permits: number);
- public wait(): Promise<void>;
- public signal(): void;
- }
- export default Semaphore;
-}
-
// web3-provider-engine declarations
declare module 'web3-provider-engine/subproviders/subprovider' {
class Subprovider {}
@@ -141,3 +131,18 @@ declare module '*.json' {
export default json;
/* tslint:enable */
}
+
+// ganache-core 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..b67b49bee 100644
--- a/packages/subproviders/src/subproviders/ledger.ts
+++ b/packages/subproviders/src/subproviders/ledger.ts
@@ -4,8 +4,8 @@ import EthereumTx = require('ethereumjs-tx');
import ethUtil = require('ethereumjs-util');
import HDNode = require('hdkey');
import * as _ from 'lodash';
-import Semaphore from 'semaphore-async-await';
-import Web3 = require('web3');
+import { Lock } from 'semaphore-async-await';
+import * as Web3 from 'web3';
import {
LedgerEthereumClient,
@@ -24,8 +24,8 @@ const ASK_FOR_ON_DEVICE_CONFIRMATION = false;
const SHOULD_GET_CHAIN_CODE = true;
export class LedgerSubprovider extends Subprovider {
- private _nonceLock: Semaphore;
- private _connectionLock: Semaphore;
+ private _nonceLock = new Lock();
+ private _connectionLock = new Lock();
private _networkId: number;
private _derivationPath: string;
private _derivationPathIndex: number;
@@ -39,8 +39,6 @@ export class LedgerSubprovider extends Subprovider {
}
constructor(config: LedgerSubproviderConfigs) {
super();
- this._nonceLock = new Semaphore(1);
- this._connectionLock = new Semaphore(1);
this._networkId = config.networkId;
this._ledgerEthereumClientFactoryAsync = config.ledgerEthereumClientFactoryAsync;
this._derivationPath = config.derivationPath || DEFAULT_DERIVATION_PATH;
@@ -147,7 +145,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;
@@ -221,27 +219,27 @@ export class LedgerSubprovider extends Subprovider {
return derivationPath;
}
private async _createLedgerClientAsync(): Promise<LedgerEthereumClient> {
- await this._connectionLock.wait();
+ await this._connectionLock.acquire();
if (!_.isUndefined(this._ledgerClientIfExists)) {
- this._connectionLock.signal();
+ this._connectionLock.release();
throw new Error(LedgerSubproviderErrors.MultipleOpenConnectionsDisallowed);
}
const ledgerEthereumClient = await this._ledgerEthereumClientFactoryAsync();
- this._connectionLock.signal();
+ this._connectionLock.release();
return ledgerEthereumClient;
}
private async _destroyLedgerClientAsync() {
- await this._connectionLock.wait();
+ await this._connectionLock.acquire();
if (_.isUndefined(this._ledgerClientIfExists)) {
- this._connectionLock.signal();
+ this._connectionLock.release();
return;
}
await this._ledgerClientIfExists.transport.close();
this._ledgerClientIfExists = undefined;
- this._connectionLock.signal();
+ this._connectionLock.release();
}
private async _sendTransactionAsync(txParams: PartialTxParams): Promise<string> {
- await this._nonceLock.wait();
+ await this._nonceLock.acquire();
try {
// fill in the extras
const filledParams = await this._populateMissingTxParamsAsync(txParams);
@@ -253,29 +251,29 @@ export class LedgerSubprovider extends Subprovider {
params: [signedTx],
};
const result = await this.emitPayloadAsync(payload);
- this._nonceLock.signal();
+ this._nonceLock.release();
return result.result;
} catch (err) {
- this._nonceLock.signal();
+ this._nonceLock.release();
throw err;
}
}
private async _signTransactionWithoutSendingAsync(txParams: PartialTxParams): Promise<ResponseWithTxParams> {
- await this._nonceLock.wait();
+ await this._nonceLock.acquire();
try {
// fill in the extras
const filledParams = await this._populateMissingTxParamsAsync(txParams);
// sign it
const signedTx = await this.signTransactionAsync(filledParams);
- this._nonceLock.signal();
+ this._nonceLock.release();
const result = {
raw: signedTx,
tx: txParams,
};
return result;
} catch (err) {
- this._nonceLock.signal();
+ this._nonceLock.release();
throw err;
}
}
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;