aboutsummaryrefslogtreecommitdiffstats
path: root/packages/subproviders/src
diff options
context:
space:
mode:
authorLeonid Logvinov <logvinov.leon@gmail.com>2018-03-24 02:18:31 +0800
committerGitHub <noreply@github.com>2018-03-24 02:18:31 +0800
commitf30353087f9c4ec4fa5e096a065c9749e1164984 (patch)
tree4d7968160890b5efa358593e743411c7b8652556 /packages/subproviders/src
parent7ef6bd4b14b7502617c6929010d4a9991e1d577d (diff)
parentbed7d87b7ff64989051e6b2115a1c77e1e72ff55 (diff)
downloaddexon-sol-tools-f30353087f9c4ec4fa5e096a065c9749e1164984.tar
dexon-sol-tools-f30353087f9c4ec4fa5e096a065c9749e1164984.tar.gz
dexon-sol-tools-f30353087f9c4ec4fa5e096a065c9749e1164984.tar.bz2
dexon-sol-tools-f30353087f9c4ec4fa5e096a065c9749e1164984.tar.lz
dexon-sol-tools-f30353087f9c4ec4fa5e096a065c9749e1164984.tar.xz
dexon-sol-tools-f30353087f9c4ec4fa5e096a065c9749e1164984.tar.zst
dexon-sol-tools-f30353087f9c4ec4fa5e096a065c9749e1164984.zip
Merge branch 'development' into feature/deployer-improvements
Diffstat (limited to 'packages/subproviders/src')
-rw-r--r--packages/subproviders/src/index.ts14
-rw-r--r--packages/subproviders/src/monorepo_scripts/stage_docs.ts8
-rw-r--r--packages/subproviders/src/subproviders/empty_wallet_subprovider.ts24
-rw-r--r--packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts36
-rw-r--r--packages/subproviders/src/subproviders/ganache.ts28
-rw-r--r--packages/subproviders/src/subproviders/injected_web3.ts35
-rw-r--r--packages/subproviders/src/subproviders/ledger.ts198
-rw-r--r--packages/subproviders/src/subproviders/nonce_tracker.ts21
-rw-r--r--packages/subproviders/src/subproviders/redundant_rpc.ts24
-rw-r--r--packages/subproviders/src/subproviders/subprovider.ts31
-rw-r--r--packages/subproviders/src/types.ts14
11 files changed, 291 insertions, 142 deletions
diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts
index cafb50fe5..d88792fd0 100644
--- a/packages/subproviders/src/index.ts
+++ b/packages/subproviders/src/index.ts
@@ -2,7 +2,6 @@ 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';
@@ -12,11 +11,20 @@ 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';
+export {
+ Callback,
+ ErrorCallback,
+ NextCallback,
+ ECSignature,
+ LedgerWalletSubprovider,
+ LedgerCommunicationClient,
+ NonceSubproviderErrors,
+ LedgerSubproviderConfigs,
+} from './types';
/**
* A factory method for creating a LedgerEthereumClient usable in a browser context.
- * @return LedgerEthereumClient A browser client
+ * @return LedgerEthereumClient A browser client for the LedgerSubprovider
*/
export async function ledgerEthereumBrowserClientFactoryAsync(): Promise<LedgerEthereumClient> {
const ledgerConnection = await TransportU2F.create();
diff --git a/packages/subproviders/src/monorepo_scripts/stage_docs.ts b/packages/subproviders/src/monorepo_scripts/stage_docs.ts
new file mode 100644
index 000000000..e732ac8eb
--- /dev/null
+++ b/packages/subproviders/src/monorepo_scripts/stage_docs.ts
@@ -0,0 +1,8 @@
+import { postpublishUtils } from '@0xproject/monorepo-scripts';
+
+import * as packageJSON from '../package.json';
+import * as tsConfigJSON from '../tsconfig.json';
+
+const cwd = `${__dirname}/..`;
+// tslint:disable-next-line:no-floating-promises
+postpublishUtils.publishDocsToStagingAsync(packageJSON, tsConfigJSON, cwd);
diff --git a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
index f5983dd9b..dc570b152 100644
--- a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
+++ b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
@@ -1,20 +1,24 @@
import * as Web3 from 'web3';
+import { Callback, ErrorCallback } from '../types';
+
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
+/**
+ * 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 needs to be here to satisfy the interface but linter wants it to be static.
+ /**
+ * 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
- public handleRequest(
- payload: Web3.JSONRPCRequestPayload,
- next: () => void,
- end: (err: Error | null, result: any) => void,
- ) {
+ public handleRequest(payload: Web3.JSONRPCRequestPayload, next: Callback, end: ErrorCallback) {
switch (payload.method) {
case 'eth_accounts':
end(null, []);
diff --git a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
index 2421dcd02..a6f978db1 100644
--- a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
+++ b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
@@ -1,28 +1,38 @@
import * as Web3 from 'web3';
+import { Callback, ErrorCallback } from '../types';
+
import { Subprovider } from './subprovider';
-/*
- * 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
+// 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 _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 needs to be here to satisfy the interface but linter wants it to be static.
+ /**
+ * 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
- public handleRequest(
- payload: Web3.JSONRPCRequestPayload,
- next: () => void,
- end: (err: Error | null, result: any) => void,
- ) {
+ public handleRequest(payload: Web3.JSONRPCRequestPayload, next: Callback, end: ErrorCallback) {
switch (payload.method) {
case 'eth_estimateGas':
end(null, this._constantGasAmount);
diff --git a/packages/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts
index a979aecf4..fc0b9c3d2 100644
--- a/packages/subproviders/src/subproviders/ganache.ts
+++ b/packages/subproviders/src/subproviders/ganache.ts
@@ -1,26 +1,34 @@
import * as Ganache from 'ganache-core';
import * as Web3 from 'web3';
+import { Callback, ErrorCallback } from '../types';
+
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
+/**
+ * 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 _ganacheProvider: Web3.Provider;
+ /**
+ * Instantiates a GanacheSubprovider
+ * @param opts The desired opts with which to instantiate the Ganache 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.
+ /**
+ * 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
- public handleRequest(
- payload: Web3.JSONRPCRequestPayload,
- next: () => void,
- end: (err: Error | null, result: any) => void,
- ) {
+ public handleRequest(payload: Web3.JSONRPCRequestPayload, next: Callback, end: ErrorCallback) {
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 6d4e2b27b..cd9b0b603 100644
--- a/packages/subproviders/src/subproviders/injected_web3.ts
+++ b/packages/subproviders/src/subproviders/injected_web3.ts
@@ -1,25 +1,36 @@
import * as _ from 'lodash';
import * as Web3 from 'web3';
+import { Callback, ErrorCallback } from '../types';
+
import { Subprovider } from './subprovider';
-/*
- * This class implements the web3-provider-engine subprovider interface and forwards
- * requests involving user accounts (getAccounts, sendTransaction, etc...) to the injected
- * provider instance in their browser.
- * 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 forwards JSON RPC requests involving user accounts (getAccounts,
+ * sendTransaction, etc...) to the provider instance supplied at instantiation. All other requests
+ * are passed onwards for subsequent subproviders to handle.
*/
export class InjectedWeb3Subprovider extends Subprovider {
private _injectedWeb3: Web3;
- constructor(subprovider: Web3.Provider) {
+ /**
+ * Instantiates a new InjectedWeb3Subprovider
+ * @param provider Web3 provider that should handle all user account related requests
+ */
+ constructor(provider: Web3.Provider) {
super();
- this._injectedWeb3 = new Web3(subprovider);
+ this._injectedWeb3 = new Web3(provider);
}
- public handleRequest(
- payload: Web3.JSONRPCRequestPayload,
- next: () => void,
- end: (err: Error | null, result: any) => void,
- ) {
+ /**
+ * 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
+ public handleRequest(payload: Web3.JSONRPCRequestPayload, next: Callback, end: ErrorCallback) {
switch (payload.method) {
case 'web3_clientVersion':
this._injectedWeb3.version.getNode(end);
diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts
index b67b49bee..8bc70d8b6 100644
--- a/packages/subproviders/src/subproviders/ledger.ts
+++ b/packages/subproviders/src/subproviders/ledger.ts
@@ -8,6 +8,7 @@ import { Lock } from 'semaphore-async-await';
import * as Web3 from 'web3';
import {
+ Callback,
LedgerEthereumClient,
LedgerEthereumClientFactoryAsync,
LedgerSubproviderConfigs,
@@ -23,6 +24,11 @@ const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10;
const ASK_FOR_ON_DEVICE_CONFIRMATION = false;
const SHOULD_GET_CHAIN_CODE = true;
+/**
+ * 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 Subprovider {
private _nonceLock = new Lock();
private _connectionLock = new Lock();
@@ -37,6 +43,12 @@ export class LedgerSubprovider extends Subprovider {
throw new Error(LedgerSubproviderErrors.SenderInvalidOrNotSupplied);
}
}
+ /**
+ * 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;
@@ -49,84 +61,38 @@ export class LedgerSubprovider extends Subprovider {
: ASK_FOR_ON_DEVICE_CONFIRMATION;
this._derivationPathIndex = 0;
}
+ /**
+ * Retrieve the set derivation path
+ * @returns derivation path
+ */
public getPath(): string {
return this._derivationPath;
}
+ /**
+ * Set a desired derivation path when computing the available user addresses
+ * @param derivationPath The desired derivation path (e.g `44'/60'/0'`)
+ */
public setPath(derivationPath: string) {
this._derivationPath = derivationPath;
}
+ /**
+ * Set the final derivation path index. If a user wishes to sign a message with the
+ * 6th address in a derivation path, before calling `signPersonalMessageAsync`, you must
+ * call this method with pathIndex `6`.
+ * @param pathIndex Desired derivation path index
+ */
public setPathIndex(pathIndex: number) {
this._derivationPathIndex = pathIndex;
}
- // Required to implement this public interface which doesn't conform to our linting rule.
- // tslint:disable-next-line:async-suffix
- public async handleRequest(
- payload: Web3.JSONRPCRequestPayload,
- next: () => void,
- end: (err: Error | null, result?: any) => void,
- ) {
- let accounts;
- let txParams;
- 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 {
- LedgerSubprovider._validateSender(txParams.from);
- const result = await this._sendTransactionAsync(txParams);
- end(null, result);
- } catch (err) {
- end(err);
- }
- return;
-
- case 'eth_signTransaction':
- txParams = payload.params[0];
- try {
- const result = await this._signTransactionWithoutSendingAsync(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];
- try {
- if (_.isUndefined(data)) {
- throw new Error(LedgerSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isHexString('data', data);
- const ecSignatureHex = await this.signPersonalMessageAsync(data);
- end(null, ecSignatureHex);
- } catch (err) {
- end(err);
- }
- return;
-
- default:
- next();
- return;
- }
- }
+ /**
+ * Retrieve a users Ledger accounts. The accounts are derived from the derivationPath,
+ * master public key and chainCode. 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[]> {
this._ledgerClientIfExists = await this._createLedgerClientAsync();
@@ -158,6 +124,14 @@ export class LedgerSubprovider extends Subprovider {
}
return accounts;
}
+ /**
+ * Sign a transaction with the Ledger. 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> {
this._ledgerClientIfExists = await this._createLedgerClientAsync();
@@ -193,6 +167,16 @@ export class LedgerSubprovider extends Subprovider {
throw err;
}
}
+ /**
+ * Sign a personal Ethereum signed message. The signing address will be to one
+ * retrieved given a derivationPath and pathIndex set on the subprovider.
+ * 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 Message to sign
+ * @return Signature hex string (order: rsv)
+ */
public async signPersonalMessageAsync(data: string): Promise<string> {
this._ledgerClientIfExists = await this._createLedgerClientAsync();
try {
@@ -214,6 +198,82 @@ export class LedgerSubprovider extends Subprovider {
throw err;
}
}
+ /**
+ * 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: Web3.JSONRPCRequestPayload,
+ next: Callback,
+ end: (err: Error | null, result?: any) => void,
+ ) {
+ let accounts;
+ let txParams;
+ 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 {
+ LedgerSubprovider._validateSender(txParams.from);
+ const result = await this._sendTransactionAsync(txParams);
+ end(null, result);
+ } catch (err) {
+ end(err);
+ }
+ return;
+
+ case 'eth_signTransaction':
+ txParams = payload.params[0];
+ try {
+ const result = await this._signTransactionWithoutSendingAsync(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];
+ try {
+ if (_.isUndefined(data)) {
+ throw new Error(LedgerSubproviderErrors.DataMissingForSignPersonalMessage);
+ }
+ assert.isHexString('data', data);
+ const ecSignatureHex = await this.signPersonalMessageAsync(data);
+ end(null, ecSignatureHex);
+ } catch (err) {
+ end(err);
+ }
+ return;
+
+ default:
+ next();
+ return;
+ }
+ }
private _getDerivationPath() {
const derivationPath = `${this.getPath()}/${this._derivationPathIndex}`;
return derivationPath;
diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts
index 82eab4a9a..249f16199 100644
--- a/packages/subproviders/src/subproviders/nonce_tracker.ts
+++ b/packages/subproviders/src/subproviders/nonce_tracker.ts
@@ -10,13 +10,13 @@ import { Callback, ErrorCallback, NextCallback, NonceSubproviderErrors } from '.
import { Subprovider } from './subprovider';
-// We do not export this since this is not our error, and we do not throw this error
const NONCE_TOO_LOW_ERROR_MESSAGE = 'Transaction nonce is too low';
-/*
- This class is heavily inspiried by the Web3ProviderEngine NonceSubprovider
- We have added the additional feature of clearing any nonce balues when an error message
- describes a nonce value being 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 _nonceCache: { [address: string]: string } = {};
private static _reconstructTransaction(payload: Web3.JSONRPCRequestPayload): EthereumTx {
@@ -46,7 +46,14 @@ export class NonceTrackerSubprovider extends Subprovider {
throw new Error(NonceSubproviderErrors.CannotDetermineAddressFromPayload);
}
}
- // Required to implement this public interface which doesn't conform to our linting rule.
+ /**
+ * 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: Web3.JSONRPCRequestPayload,
diff --git a/packages/subproviders/src/subproviders/redundant_rpc.ts b/packages/subproviders/src/subproviders/redundant_rpc.ts
index 0df2f91f4..ace2ed3c8 100644
--- a/packages/subproviders/src/subproviders/redundant_rpc.ts
+++ b/packages/subproviders/src/subproviders/redundant_rpc.ts
@@ -3,14 +3,21 @@ import * as _ from 'lodash';
import * as Web3 from 'web3';
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
+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 RedundantRPCSubprovider extends Subprovider {
private _rpcs: RpcSubprovider[];
private static async _firstSuccessAsync(
rpcs: RpcSubprovider[],
payload: Web3.JSONRPCRequestPayload,
- next: () => void,
+ next: Callback,
): Promise<any> {
let lastErr: Error | undefined;
for (const rpc of rpcs) {
@@ -26,6 +33,10 @@ export class RedundantRPCSubprovider extends Subprovider {
throw lastErr;
}
}
+ /**
+ * Instantiates a new RedundantRPCSubprovider
+ * @param endpoints JSON RPC endpoints to attempt. Attempts are made in the order of the endpoints.
+ */
constructor(endpoints: string[]) {
super();
this._rpcs = _.map(endpoints, endpoint => {
@@ -34,11 +45,18 @@ export class RedundantRPCSubprovider extends Subprovider {
});
});
}
- // Required to implement this public interface which doesn't conform to our linting rule.
+ /**
+ * 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: Web3.JSONRPCRequestPayload,
- next: () => void,
+ next: Callback,
end: (err: Error | null, data?: any) => void,
): Promise<void> {
const rpcsCopy = this._rpcs.slice();
diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts
index d4e0de67a..4fa351e11 100644
--- a/packages/subproviders/src/subproviders/subprovider.ts
+++ b/packages/subproviders/src/subproviders/subprovider.ts
@@ -1,9 +1,10 @@
import promisify = require('es6-promisify');
import * as Web3 from 'web3';
-/*
- * A version of the base class Subprovider found in providerEngine
+
+import { 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.
- * Altered version of: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
*/
export class Subprovider {
private _engine: any;
@@ -18,8 +19,8 @@ export class Subprovider {
return datePart + extraPart;
}
private static _createFinalPayload(
- payload: Partial<Web3.JSONRPCRequestPayload> & { method: string },
- ): Web3.JSONRPCRequestPayload {
+ payload: Partial<JSONRPCRequestPayloadWithMethod>,
+ ): Partial<JSONRPCRequestPayloadWithMethod> {
const finalPayload = {
// defaults
id: Subprovider._getRandomId(),
@@ -29,14 +30,26 @@ export class Subprovider {
};
return finalPayload;
}
- public setEngine(engine: any): void {
- this._engine = engine;
- }
+ /**
+ * 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<Web3.JSONRPCRequestPayload> & { method: string },
+ payload: Partial<JSONRPCRequestPayloadWithMethod>,
): Promise<Web3.JSONRPCResponsePayload> {
const finalPayload = Subprovider._createFinalPayload(payload);
const response = await promisify(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.
+ */
+ public setEngine(engine: any): void {
+ this._engine = engine;
+ }
}
diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts
index 543da5947..9bb9ff696 100644
--- a/packages/subproviders/src/types.ts
+++ b/packages/subproviders/src/types.ts
@@ -1,4 +1,8 @@
+import { ECSignature } from '@0xproject/types';
import * as _ from 'lodash';
+import * as Web3 from 'web3';
+
+export { ECSignature } from '@0xproject/types';
export interface LedgerCommunicationClient {
close: () => Promise<void>;
@@ -28,12 +32,6 @@ export interface ECSignatureString {
s: string;
}
-export interface ECSignature {
- v: number;
- r: string;
- s: string;
-}
-
export type LedgerEthereumClientFactoryAsync = () => Promise<LedgerEthereumClient>;
/*
@@ -117,3 +115,7 @@ 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 Web3.JSONRPCRequestPayload {
+ method: string;
+}