aboutsummaryrefslogtreecommitdiffstats
path: root/packages/subproviders/src
diff options
context:
space:
mode:
authorHsuan Lee <boczeratul@gmail.com>2019-03-06 17:46:50 +0800
committerHsuan Lee <boczeratul@gmail.com>2019-03-06 17:46:50 +0800
commit35703539d0f2b4ddb3b11d0de8c9634af59ab71f (patch)
treeae3731221dbbb3a6fa40060a8d916cfd3f738289 /packages/subproviders/src
parent92a1fde5b1ecd81b07cdb5bf0c9c1cd3544799db (diff)
downloaddexon-0x-contracts-stable.tar
dexon-0x-contracts-stable.tar.gz
dexon-0x-contracts-stable.tar.bz2
dexon-0x-contracts-stable.tar.lz
dexon-0x-contracts-stable.tar.xz
dexon-0x-contracts-stable.tar.zst
dexon-0x-contracts-stable.zip
Deploy @dexon-foundation/0x.jsstable
Diffstat (limited to 'packages/subproviders/src')
-rw-r--r--packages/subproviders/src/globals.d.ts24
-rw-r--r--packages/subproviders/src/index.ts59
-rw-r--r--packages/subproviders/src/subproviders/base_wallet_subprovider.ts151
-rw-r--r--packages/subproviders/src/subproviders/empty_wallet_subprovider.ts32
-rw-r--r--packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts91
-rw-r--r--packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts46
-rw-r--r--packages/subproviders/src/subproviders/ganache.ts36
-rw-r--r--packages/subproviders/src/subproviders/ledger.ts256
-rw-r--r--packages/subproviders/src/subproviders/metamask_subprovider.ts126
-rw-r--r--packages/subproviders/src/subproviders/mnemonic_wallet.ts164
-rw-r--r--packages/subproviders/src/subproviders/nonce_tracker.ts110
-rw-r--r--packages/subproviders/src/subproviders/private_key_wallet.ts114
-rw-r--r--packages/subproviders/src/subproviders/redundant_subprovider.ts65
-rw-r--r--packages/subproviders/src/subproviders/rpc_subprovider.ts94
-rw-r--r--packages/subproviders/src/subproviders/signer.ts86
-rw-r--r--packages/subproviders/src/subproviders/subprovider.ts70
-rw-r--r--packages/subproviders/src/types.ts138
-rw-r--r--packages/subproviders/src/utils/subprovider_utils.ts15
-rw-r--r--packages/subproviders/src/utils/wallet_utils.ts79
19 files changed, 0 insertions, 1756 deletions
diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts
deleted file mode 100644
index 3cbf84e37..000000000
--- a/packages/subproviders/src/globals.d.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-declare module '*.json' {
- const json: any;
- /* tslint:disable */
- export default json;
- /* tslint:enable */
-}
-declare module 'web3-provider-engine/util/rpc-cache-utils' {
- class ProviderEngineRpcUtils {
- public static blockTagForPayload(payload: any): string | null;
- }
- export = ProviderEngineRpcUtils;
-}
-declare module 'web3-provider-engine/subproviders/fixture' {
- import { JSONRPCRequestPayload, JSONRPCResponsePayload } from 'ethereum-types';
- class FixtureSubprovider {
- constructor(staticResponses: any);
- public handleRequest(
- payload: JSONRPCRequestPayload,
- next: () => void,
- end: (err: Error | null, data?: JSONRPCResponsePayload) => void,
- ): void;
- }
- export = FixtureSubprovider;
-}
diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts
deleted file mode 100644
index 050027f96..000000000
--- a/packages/subproviders/src/index.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import Eth from '@ledgerhq/hw-app-eth';
-import TransportU2F from '@ledgerhq/hw-transport-u2f';
-export import Web3ProviderEngine = require('web3-provider-engine');
-
-import { LedgerEthereumClient } from './types';
-
-/**
- * A factory method for creating a LedgerEthereumClient usable in a browser context.
- * @return LedgerEthereumClient A browser client for the LedgerSubprovider
- */
-export async function ledgerEthereumBrowserClientFactoryAsync(): Promise<LedgerEthereumClient> {
- const ledgerConnection = await TransportU2F.create();
- const ledgerEthClient = new Eth(ledgerConnection);
- return ledgerEthClient;
-}
-
-export { prependSubprovider } from './utils/subprovider_utils';
-
-export { EmptyWalletSubprovider } from './subproviders/empty_wallet_subprovider';
-export { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_subprovider';
-export { SignerSubprovider } from './subproviders/signer';
-export { RedundantSubprovider } from './subproviders/redundant_subprovider';
-export { LedgerSubprovider } from './subproviders/ledger';
-export { RPCSubprovider } from './subproviders/rpc_subprovider';
-export { GanacheSubprovider } from './subproviders/ganache';
-export { Subprovider } from './subproviders/subprovider';
-export { NonceTrackerSubprovider } from './subproviders/nonce_tracker';
-export { PrivateKeyWalletSubprovider } from './subproviders/private_key_wallet';
-export { MnemonicWalletSubprovider } from './subproviders/mnemonic_wallet';
-export { MetamaskSubprovider } from './subproviders/metamask_subprovider';
-export { EthLightwalletSubprovider } from './subproviders/eth_lightwallet_subprovider';
-
-export {
- Callback,
- ErrorCallback,
- NextCallback,
- LedgerCommunicationClient,
- LedgerEthereumClient,
- NonceSubproviderErrors,
- LedgerSubproviderConfigs,
- PartialTxParams,
- JSONRPCRequestPayloadWithMethod,
- ECSignatureString,
- AccountFetchingConfigs,
- LedgerEthereumClientFactoryAsync,
- OnNextCompleted,
- MnemonicWalletSubproviderConfigs,
- LedgerGetAddressResult,
-} from './types';
-
-export { ECSignature, EIP712Object, EIP712ObjectValue, EIP712TypedData, EIP712Types, EIP712Parameter } from '@0x/types';
-
-export {
- JSONRPCRequestPayload,
- Provider,
- JSONRPCResponsePayload,
- JSONRPCErrorCallback,
- JSONRPCResponseError,
-} from 'ethereum-types';
diff --git a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts b/packages/subproviders/src/subproviders/base_wallet_subprovider.ts
deleted file mode 100644
index e9d104074..000000000
--- a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-import { assert } from '@0x/assert';
-import { addressUtils } from '@0x/utils';
-import { JSONRPCRequestPayload, JSONRPCResponsePayload } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { Callback, ErrorCallback, PartialTxParams, WalletSubproviderErrors } from '../types';
-
-import { Subprovider } from './subprovider';
-
-export abstract class BaseWalletSubprovider extends Subprovider {
- protected static _validateTxParams(txParams: PartialTxParams): void {
- if (!_.isUndefined(txParams.to)) {
- assert.isETHAddressHex('to', txParams.to);
- }
- assert.isHexString('nonce', txParams.nonce);
- }
- private static _validateSender(sender: string): void {
- if (_.isUndefined(sender) || !addressUtils.isAddress(sender)) {
- throw new Error(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
- }
- }
-
- public abstract async getAccountsAsync(): Promise<string[]>;
- public abstract async signTransactionAsync(txParams: PartialTxParams): Promise<string>;
- public abstract async signPersonalMessageAsync(data: string, address: string): Promise<string>;
- public abstract async signTypedDataAsync(address: string, typedData: any): Promise<string>;
-
- /**
- * 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: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- let accounts;
- let txParams;
- let address;
- let typedData;
- 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 {
- BaseWalletSubprovider._validateSender(txParams.from);
- const filledParams = await this._populateMissingTxParamsAsync(txParams);
- const signedTx = await this.signTransactionAsync(filledParams);
- const response = await this._emitSendTransactionAsync(signedTx);
- end(null, response.result);
- } catch (err) {
- end(err);
- }
- return;
-
- case 'eth_signTransaction':
- txParams = payload.params[0];
- try {
- const filledParams = await this._populateMissingTxParamsAsync(txParams);
- const signedTx = await this.signTransactionAsync(filledParams);
- const result = {
- raw: signedTx,
- tx: 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];
- address = payload.method === 'eth_sign' ? payload.params[0] : payload.params[1];
- try {
- const ecSignatureHex = await this.signPersonalMessageAsync(data, address);
- end(null, ecSignatureHex);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_signTypedData':
- [address, typedData] = payload.params;
- try {
- const signature = await this.signTypedDataAsync(address, typedData);
- end(null, signature);
- } catch (err) {
- end(err);
- }
- return;
-
- default:
- next();
- return;
- }
- }
- private async _emitSendTransactionAsync(signedTx: string): Promise<JSONRPCResponsePayload> {
- const payload = {
- method: 'eth_sendRawTransaction',
- params: [signedTx],
- };
- const result = await this.emitPayloadAsync(payload);
- return result;
- }
- private async _populateMissingTxParamsAsync(partialTxParams: PartialTxParams): Promise<PartialTxParams> {
- let txParams = partialTxParams;
- if (_.isUndefined(partialTxParams.gasPrice)) {
- const gasPriceResult = await this.emitPayloadAsync({
- method: 'eth_gasPrice',
- params: [],
- });
- const gasPrice = gasPriceResult.result.toString();
- txParams = { ...txParams, gasPrice };
- }
- if (_.isUndefined(partialTxParams.nonce)) {
- const nonceResult = await this.emitPayloadAsync({
- method: 'eth_getTransactionCount',
- params: [partialTxParams.from, 'pending'],
- });
- const nonce = nonceResult.result;
- txParams = { ...txParams, nonce };
- }
- if (_.isUndefined(partialTxParams.gas)) {
- const gasResult = await this.emitPayloadAsync({
- method: 'eth_estimateGas',
- params: [partialTxParams],
- });
- const gas = gasResult.result.toString();
- txParams = { ...txParams, gas };
- }
- return txParams;
- }
-}
diff --git a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
deleted file mode 100644
index 4268c67bd..000000000
--- a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { JSONRPCRequestPayload } from 'ethereum-types';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * 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 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 async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- switch (payload.method) {
- case 'eth_accounts':
- end(null, []);
- return;
-
- default:
- next();
- return;
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
deleted file mode 100644
index 15cd713af..000000000
--- a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import { EIP712TypedData } from '@0x/types';
-import * as lightwallet from 'eth-lightwallet';
-
-import { PartialTxParams } from '../types';
-
-import { BaseWalletSubprovider } from './base_wallet_subprovider';
-import { PrivateKeyWalletSubprovider } from './private_key_wallet';
-
-/*
- * This class implements the web3-provider-engine subprovider interface and forwards
- * requests involving user accounts and signing operations to eth-lightwallet
- *
- * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
- */
-export class EthLightwalletSubprovider extends BaseWalletSubprovider {
- private readonly _keystore: lightwallet.keystore;
- private readonly _pwDerivedKey: Uint8Array;
- /**
- * Instantiate an EthLightwalletSubprovider
- * @param keystore The EthLightWallet keystore you wish to use
- * @param pwDerivedKey The password derived key to use
- * @return EthLightwalletSubprovider instance
- */
- constructor(keystore: lightwallet.keystore, pwDerivedKey: Uint8Array) {
- super();
- this._keystore = keystore;
- this._pwDerivedKey = pwDerivedKey;
- }
- /**
- * Retrieve the accounts associated with the eth-lightwallet instance.
- * This method is implicitly called when issuing a `eth_accounts` JSON RPC request
- * via your providerEngine instance.
- *
- * @return An array of accounts
- */
- public async getAccountsAsync(): Promise<string[]> {
- const accounts = this._keystore.getAddresses();
- return accounts;
- }
- /**
- * Signs a transaction with the account specificed by the `from` field in txParams.
- * If you've added this Subprovider 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> {
- // Lightwallet loses the chain id information when hex encoding the transaction
- // this results in a different signature on certain networks. PrivateKeyWallet
- // respects this as it uses the parameters passed in
- let privateKey = this._keystore.exportPrivateKey(txParams.from, this._pwDerivedKey);
- const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
- privateKey = '';
- const privateKeySignature = await privateKeyWallet.signTransactionAsync(txParams);
- return privateKeySignature;
- }
- /**
- * Sign a personal Ethereum signed message. The signing account will be the account
- * associated with the provided address.
- * If you've added this Subprovider 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 Hex string message to sign
- * @param address Address of the account to sign with
- * @return Signature hex string (order: rsv)
- */
- public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- let privateKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey);
- const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
- privateKey = '';
- const result = privateKeyWallet.signPersonalMessageAsync(data, address);
- return result;
- }
- /**
- * Sign an EIP712 Typed Data message. The signing address will associated with the provided address.
- * If you've added this Subprovider to your app's provider, you can simply send an `eth_signTypedData`
- * 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 address Address of the account to sign with
- * @param data the typed data object
- * @return Signature hex string (order: rsv)
- */
- public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
- let privateKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey);
- const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
- privateKey = '';
- const result = privateKeyWallet.signTypedDataAsync(address, typedData);
- return result;
- }
-}
diff --git a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
deleted file mode 100644
index bc1b34aba..000000000
--- a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { JSONRPCRequestPayload } from 'ethereum-types';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-// 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 readonly _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 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 async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- switch (payload.method) {
- case 'eth_estimateGas':
- end(null, this._constantGasAmount);
- return;
-
- default:
- next();
- return;
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts
deleted file mode 100644
index 2b8544f8b..000000000
--- a/packages/subproviders/src/subproviders/ganache.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { JSONRPCRequestPayload, Provider } from 'ethereum-types';
-import * as Ganache from 'ganache-core';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * 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 readonly _ganacheProvider: Provider;
- /**
- * Instantiates a GanacheSubprovider
- * @param opts The desired opts with which to instantiate the Ganache provider
- */
- constructor(opts: Ganache.GanacheOpts) {
- super();
- this._ganacheProvider = Ganache.provider(opts);
- }
- /**
- * 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 async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, _next: Callback, end: ErrorCallback): Promise<void> {
- this._ganacheProvider.sendAsync(payload, (err: Error | null, result: any) => {
- end(err, result && result.result);
- });
- }
-}
diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts
deleted file mode 100644
index b5ca10ce1..000000000
--- a/packages/subproviders/src/subproviders/ledger.ts
+++ /dev/null
@@ -1,256 +0,0 @@
-import { assert } from '@0x/assert';
-import { addressUtils } from '@0x/utils';
-import EthereumTx = require('ethereumjs-tx');
-import ethUtil = require('ethereumjs-util');
-import HDNode = require('hdkey');
-import * as _ from 'lodash';
-import { Lock } from 'semaphore-async-await';
-
-import {
- DerivedHDKeyInfo,
- LedgerEthereumClient,
- LedgerEthereumClientFactoryAsync,
- LedgerSubproviderConfigs,
- LedgerSubproviderErrors,
- PartialTxParams,
- WalletSubproviderErrors,
-} from '../types';
-import { walletUtils } from '../utils/wallet_utils';
-
-import { BaseWalletSubprovider } from './base_wallet_subprovider';
-
-const DEFAULT_BASE_DERIVATION_PATH = `44'/60'/0'`;
-const ASK_FOR_ON_DEVICE_CONFIRMATION = false;
-const SHOULD_GET_CHAIN_CODE = true;
-const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10;
-const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000;
-
-/**
- * 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 BaseWalletSubprovider {
- // tslint:disable-next-line:no-unused-variable
- private readonly _connectionLock = new Lock();
- private readonly _networkId: number;
- private _baseDerivationPath: string;
- private readonly _ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync;
- private _ledgerClientIfExists?: LedgerEthereumClient;
- private readonly _shouldAlwaysAskForConfirmation: boolean;
- private readonly _addressSearchLimit: number;
- /**
- * 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;
- this._ledgerEthereumClientFactoryAsync = config.ledgerEthereumClientFactoryAsync;
- this._baseDerivationPath = config.baseDerivationPath || DEFAULT_BASE_DERIVATION_PATH;
- this._shouldAlwaysAskForConfirmation =
- !_.isUndefined(config.accountFetchingConfigs) &&
- !_.isUndefined(config.accountFetchingConfigs.shouldAskForOnDeviceConfirmation)
- ? config.accountFetchingConfigs.shouldAskForOnDeviceConfirmation
- : ASK_FOR_ON_DEVICE_CONFIRMATION;
- this._addressSearchLimit =
- !_.isUndefined(config.accountFetchingConfigs) &&
- !_.isUndefined(config.accountFetchingConfigs.addressSearchLimit)
- ? config.accountFetchingConfigs.addressSearchLimit
- : DEFAULT_ADDRESS_SEARCH_LIMIT;
- }
- /**
- * Retrieve the set derivation path
- * @returns derivation path
- */
- public getPath(): string {
- return this._baseDerivationPath;
- }
- /**
- * Set a desired derivation path when computing the available user addresses
- * @param basDerivationPath The desired derivation path (e.g `44'/60'/0'`)
- */
- public setPath(basDerivationPath: string): void {
- this._baseDerivationPath = basDerivationPath;
- }
- /**
- * Retrieve a users Ledger accounts. The accounts are derived from the derivationPath,
- * master public key and chain code. 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[]> {
- const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync();
- const derivedKeyInfos = walletUtils.calculateDerivedHDKeyInfos(initialDerivedKeyInfo, numberOfAccounts);
- const accounts = _.map(derivedKeyInfos, k => k.address);
- return accounts;
- }
- /**
- * Signs a transaction on the Ledger with the account specificed by the `from` field in txParams.
- * 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> {
- LedgerSubprovider._validateTxParams(txParams);
- if (_.isUndefined(txParams.from) || !addressUtils.isAddress(txParams.from)) {
- throw new Error(WalletSubproviderErrors.FromAddressMissingOrInvalid);
- }
- const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync();
- const derivedKeyInfo = this._findDerivedKeyInfoForAddress(initialDerivedKeyInfo, txParams.from);
-
- this._ledgerClientIfExists = await this._createLedgerClientAsync();
-
- const tx = new EthereumTx(txParams);
-
- // Set the EIP155 bits
- const vIndex = 6;
- tx.raw[vIndex] = Buffer.from([this._networkId]); // v
- const rIndex = 7;
- tx.raw[rIndex] = Buffer.from([]); // r
- const sIndex = 8;
- tx.raw[sIndex] = Buffer.from([]); // s
-
- const txHex = tx.serialize().toString('hex');
- try {
- const fullDerivationPath = derivedKeyInfo.derivationPath;
- const result = await this._ledgerClientIfExists.signTransaction(fullDerivationPath, txHex);
- // Store signature in transaction
- tx.r = Buffer.from(result.r, 'hex');
- tx.s = Buffer.from(result.s, 'hex');
- tx.v = Buffer.from(result.v, 'hex');
-
- // EIP155: v should be chain_id * 2 + {35, 36}
- const eip55Constant = 35;
- const signedChainId = Math.floor((tx.v[0] - eip55Constant) / 2);
- if (signedChainId !== this._networkId) {
- await this._destroyLedgerClientAsync();
- const err = new Error(LedgerSubproviderErrors.TooOldLedgerFirmware);
- throw err;
- }
-
- const signedTxHex = `0x${tx.serialize().toString('hex')}`;
- await this._destroyLedgerClientAsync();
- return signedTxHex;
- } catch (err) {
- await this._destroyLedgerClientAsync();
- throw err;
- }
- }
- /**
- * Sign a personal Ethereum signed message. The signing account will be the account
- * associated with the provided address.
- * 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 Hex string message to sign
- * @param address Address of the account to sign with
- * @return Signature hex string (order: rsv)
- */
- public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- if (_.isUndefined(data)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isHexString('data', data);
- assert.isETHAddressHex('address', address);
- const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync();
- const derivedKeyInfo = this._findDerivedKeyInfoForAddress(initialDerivedKeyInfo, address);
-
- this._ledgerClientIfExists = await this._createLedgerClientAsync();
- try {
- const fullDerivationPath = derivedKeyInfo.derivationPath;
- const result = await this._ledgerClientIfExists.signPersonalMessage(
- fullDerivationPath,
- ethUtil.stripHexPrefix(data),
- );
- const lowestValidV = 27;
- const v = result.v - lowestValidV;
- const hexBase = 16;
- let vHex = v.toString(hexBase);
- if (vHex.length < 2) {
- vHex = `0${v}`;
- }
- const signature = `0x${result.r}${result.s}${vHex}`;
- await this._destroyLedgerClientAsync();
- return signature;
- } catch (err) {
- await this._destroyLedgerClientAsync();
- throw err;
- }
- }
- /**
- * eth_signTypedData is currently not supported on Ledger devices.
- * @param address Address of the account to sign with
- * @param data the typed data object
- * @return Signature hex string (order: rsv)
- */
- // tslint:disable-next-line:prefer-function-over-method
- public async signTypedDataAsync(address: string, typedData: any): Promise<string> {
- throw new Error(WalletSubproviderErrors.MethodNotSupported);
- }
- private async _createLedgerClientAsync(): Promise<LedgerEthereumClient> {
- await this._connectionLock.acquire();
- if (!_.isUndefined(this._ledgerClientIfExists)) {
- this._connectionLock.release();
- throw new Error(LedgerSubproviderErrors.MultipleOpenConnectionsDisallowed);
- }
- const ledgerEthereumClient = await this._ledgerEthereumClientFactoryAsync();
- this._connectionLock.release();
- return ledgerEthereumClient;
- }
- private async _destroyLedgerClientAsync(): Promise<void> {
- await this._connectionLock.acquire();
- if (_.isUndefined(this._ledgerClientIfExists)) {
- this._connectionLock.release();
- return;
- }
- await this._ledgerClientIfExists.transport.close();
- this._ledgerClientIfExists = undefined;
- this._connectionLock.release();
- }
- private async _initialDerivedKeyInfoAsync(): Promise<DerivedHDKeyInfo> {
- this._ledgerClientIfExists = await this._createLedgerClientAsync();
-
- const parentKeyDerivationPath = `m/${this._baseDerivationPath}`;
- let ledgerResponse;
- try {
- ledgerResponse = await this._ledgerClientIfExists.getAddress(
- parentKeyDerivationPath,
- this._shouldAlwaysAskForConfirmation,
- SHOULD_GET_CHAIN_CODE,
- );
- } finally {
- await this._destroyLedgerClientAsync();
- }
- const hdKey = new HDNode();
- hdKey.publicKey = new Buffer(ledgerResponse.publicKey, 'hex');
- hdKey.chainCode = new Buffer(ledgerResponse.chainCode, 'hex');
- const address = walletUtils.addressOfHDKey(hdKey);
- const initialDerivedKeyInfo = {
- hdKey,
- address,
- derivationPath: parentKeyDerivationPath,
- baseDerivationPath: this._baseDerivationPath,
- };
- return initialDerivedKeyInfo;
- }
- private _findDerivedKeyInfoForAddress(initalHDKey: DerivedHDKeyInfo, address: string): DerivedHDKeyInfo {
- const matchedDerivedKeyInfo = walletUtils.findDerivedKeyInfoForAddressIfExists(
- address,
- initalHDKey,
- this._addressSearchLimit,
- );
- if (_.isUndefined(matchedDerivedKeyInfo)) {
- throw new Error(`${WalletSubproviderErrors.AddressNotFound}: ${address}`);
- }
- return matchedDerivedKeyInfo;
- }
-}
diff --git a/packages/subproviders/src/subproviders/metamask_subprovider.ts b/packages/subproviders/src/subproviders/metamask_subprovider.ts
deleted file mode 100644
index ba207d4cc..000000000
--- a/packages/subproviders/src/subproviders/metamask_subprovider.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-import { marshaller, Web3Wrapper } from '@0x/web3-wrapper';
-import { JSONRPCRequestPayload, Provider } from 'ethereum-types';
-import * as ethUtil from 'ethereumjs-util';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine)
- * subprovider interface and the provider sendAsync interface.
- * It handles inconsistencies with Metamask implementations of various JSON RPC methods.
- * It forwards JSON RPC requests involving the domain of a signer (getAccounts,
- * sendTransaction, signMessage etc...) to the provider instance supplied at instantiation. All other requests
- * are passed onwards for subsequent subproviders to handle.
- */
-export class MetamaskSubprovider extends Subprovider {
- private readonly _web3Wrapper: Web3Wrapper;
- private readonly _provider: Provider;
- /**
- * Instantiates a new MetamaskSubprovider
- * @param provider Web3 provider that should handle all user account related requests
- */
- constructor(provider: Provider) {
- super();
- this._web3Wrapper = new Web3Wrapper(provider);
- this._provider = provider;
- }
- /**
- * 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 async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- let message;
- let address;
- switch (payload.method) {
- case 'web3_clientVersion':
- try {
- const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
- end(null, nodeVersion);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_accounts':
- try {
- const accounts = await this._web3Wrapper.getAvailableAddressesAsync();
- end(null, accounts);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_sendTransaction':
- const [txParams] = payload.params;
- try {
- const txData = marshaller.unmarshalTxData(txParams);
- const txHash = await this._web3Wrapper.sendTransactionAsync(txData);
- end(null, txHash);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_sign':
- [address, message] = payload.params;
- try {
- // Metamask incorrectly implements eth_sign and does not prefix the message as per the spec
- // Source: https://github.com/MetaMask/metamask-extension/commit/a9d36860bec424dcee8db043d3e7da6a5ff5672e
- const msgBuff = ethUtil.toBuffer(message);
- const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff);
- const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
- const signature = await this._web3Wrapper.signMessageAsync(address, prefixedMsgHex);
- signature ? end(null, signature) : end(new Error('Error performing eth_sign'), null);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_signTypedData':
- case 'eth_signTypedData_v3':
- [address, message] = payload.params;
- try {
- // Metamask supports multiple versions and has namespaced signTypedData to v3 for an indeterminate period of time.
- // eth_signTypedData is mapped to an older implementation before the spec was finalized.
- // Source: https://github.com/MetaMask/metamask-extension/blob/c49d854b55b3efd34c7fd0414b76f7feaa2eec7c/app/scripts/metamask-controller.js#L1262
- // and expects message to be serialised as JSON
- const messageJSON = JSON.stringify(message);
- const signature = await this._web3Wrapper.sendRawPayloadAsync<string>({
- method: 'eth_signTypedData_v3',
- params: [address, messageJSON],
- });
- signature ? end(null, signature) : end(new Error('Error performing eth_signTypedData'), null);
- } catch (err) {
- end(err);
- }
- return;
- default:
- next();
- return;
- }
- }
- /**
- * This method conforms to the provider sendAsync interface.
- * Allowing the MetamaskSubprovider to be used as a generic provider (outside of Web3ProviderEngine) with the
- * addition of wrapping the inconsistent Metamask behaviour
- * @param payload JSON RPC payload
- * @return The contents nested under the result key of the response body
- */
- public sendAsync(payload: JSONRPCRequestPayload, callback: ErrorCallback): void {
- void this.handleRequest(
- payload,
- // handleRequest has decided to not handle this, so fall through to the provider
- () => {
- const sendAsync = this._provider.sendAsync.bind(this._provider);
- sendAsync(payload, callback);
- },
- // handleRequest has called end and will handle this
- (err, data) => {
- err ? callback(err) : callback(null, { ...payload, result: data });
- },
- );
- }
-}
diff --git a/packages/subproviders/src/subproviders/mnemonic_wallet.ts b/packages/subproviders/src/subproviders/mnemonic_wallet.ts
deleted file mode 100644
index 140e3d515..000000000
--- a/packages/subproviders/src/subproviders/mnemonic_wallet.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-import { assert } from '@0x/assert';
-import { EIP712TypedData } from '@0x/types';
-import { addressUtils } from '@0x/utils';
-import * as bip39 from 'bip39';
-import HDNode = require('hdkey');
-import * as _ from 'lodash';
-
-import { DerivedHDKeyInfo, MnemonicWalletSubproviderConfigs, PartialTxParams, WalletSubproviderErrors } from '../types';
-import { walletUtils } from '../utils/wallet_utils';
-
-import { BaseWalletSubprovider } from './base_wallet_subprovider';
-import { PrivateKeyWalletSubprovider } from './private_key_wallet';
-
-const DEFAULT_BASE_DERIVATION_PATH = `44'/60'/0'/0`;
-const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10;
-const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000;
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * This subprovider intercepts all account related RPC requests (e.g message/transaction signing, etc...) and handles
- * all requests with accounts derived from the supplied mnemonic.
- */
-export class MnemonicWalletSubprovider extends BaseWalletSubprovider {
- private readonly _addressSearchLimit: number;
- private _baseDerivationPath: string;
- private _derivedKeyInfo: DerivedHDKeyInfo;
- private readonly _mnemonic: string;
-
- /**
- * Instantiates a MnemonicWalletSubprovider. Defaults to baseDerivationPath set to `44'/60'/0'/0`.
- * This is the default in TestRPC/Ganache, it can be overridden if desired.
- * @param config Configuration for the mnemonic wallet, must contain the mnemonic
- * @return MnemonicWalletSubprovider instance
- */
- constructor(config: MnemonicWalletSubproviderConfigs) {
- assert.isString('mnemonic', config.mnemonic);
- const baseDerivationPath = config.baseDerivationPath || DEFAULT_BASE_DERIVATION_PATH;
- assert.isString('baseDerivationPath', baseDerivationPath);
- const addressSearchLimit = config.addressSearchLimit || DEFAULT_ADDRESS_SEARCH_LIMIT;
- assert.isNumber('addressSearchLimit', addressSearchLimit);
- super();
-
- this._mnemonic = config.mnemonic;
- this._baseDerivationPath = baseDerivationPath;
- this._addressSearchLimit = addressSearchLimit;
- this._derivedKeyInfo = this._initialDerivedKeyInfo(this._baseDerivationPath);
- }
- /**
- * Retrieve the set derivation path
- * @returns derivation path
- */
- public getPath(): string {
- return this._baseDerivationPath;
- }
- /**
- * Set a desired derivation path when computing the available user addresses
- * @param baseDerivationPath The desired derivation path (e.g `44'/60'/0'`)
- */
- public setPath(baseDerivationPath: string): void {
- this._baseDerivationPath = baseDerivationPath;
- this._derivedKeyInfo = this._initialDerivedKeyInfo(this._baseDerivationPath);
- }
- /**
- * Retrieve the accounts associated with the mnemonic.
- * This method is implicitly 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[]> {
- const derivedKeys = walletUtils.calculateDerivedHDKeyInfos(this._derivedKeyInfo, numberOfAccounts);
- const accounts = _.map(derivedKeys, k => k.address);
- return accounts;
- }
-
- /**
- * Signs a transaction with the account specificed by the `from` field in txParams.
- * If you've added this Subprovider 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> {
- if (_.isUndefined(txParams.from) || !addressUtils.isAddress(txParams.from)) {
- throw new Error(WalletSubproviderErrors.FromAddressMissingOrInvalid);
- }
- const privateKeyWallet = this._privateKeyWalletForAddress(txParams.from);
- const signedTx = privateKeyWallet.signTransactionAsync(txParams);
- return signedTx;
- }
- /**
- * Sign a personal Ethereum signed message. The signing account will be the account
- * associated with the provided address. If you've added the MnemonicWalletSubprovider 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 Hex string message to sign
- * @param address Address of the account to sign with
- * @return Signature hex string (order: rsv)
- */
- public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- if (_.isUndefined(data)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isHexString('data', data);
- assert.isETHAddressHex('address', address);
- const privateKeyWallet = this._privateKeyWalletForAddress(address);
- const sig = await privateKeyWallet.signPersonalMessageAsync(data, address);
- return sig;
- }
- /**
- * Sign an EIP712 Typed Data message. The signing account will be the account
- * associated with the provided address. If you've added this MnemonicWalletSubprovider to
- * your app's provider, you can simply send an `eth_signTypedData` 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 address Address of the account to sign with
- * @param data the typed data object
- * @return Signature hex string (order: rsv)
- */
- public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
- if (_.isUndefined(typedData)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isETHAddressHex('address', address);
- const privateKeyWallet = this._privateKeyWalletForAddress(address);
- const sig = await privateKeyWallet.signTypedDataAsync(address, typedData);
- return sig;
- }
- private _privateKeyWalletForAddress(address: string): PrivateKeyWalletSubprovider {
- const derivedKeyInfo = this._findDerivedKeyInfoForAddress(address);
- const privateKeyHex = derivedKeyInfo.hdKey.privateKey.toString('hex');
- const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKeyHex);
- return privateKeyWallet;
- }
- private _findDerivedKeyInfoForAddress(address: string): DerivedHDKeyInfo {
- const matchedDerivedKeyInfo = walletUtils.findDerivedKeyInfoForAddressIfExists(
- address,
- this._derivedKeyInfo,
- this._addressSearchLimit,
- );
- if (_.isUndefined(matchedDerivedKeyInfo)) {
- throw new Error(`${WalletSubproviderErrors.AddressNotFound}: ${address}`);
- }
- return matchedDerivedKeyInfo;
- }
- private _initialDerivedKeyInfo(baseDerivationPath: string): DerivedHDKeyInfo {
- const seed = bip39.mnemonicToSeed(this._mnemonic);
- const hdKey = HDNode.fromMasterSeed(seed);
- // Walk down to base derivation level (i.e m/44'/60'/0') and create an initial key at that level
- // all children will then be walked relative (i.e m/0)
- const parentKeyDerivationPath = `m/${baseDerivationPath}`;
- const parentHDKeyAtDerivationPath = hdKey.derive(parentKeyDerivationPath);
- const address = walletUtils.addressOfHDKey(parentHDKeyAtDerivationPath);
- const derivedKeyInfo = {
- address,
- baseDerivationPath,
- derivationPath: parentKeyDerivationPath,
- hdKey: parentHDKeyAtDerivationPath,
- };
- return derivedKeyInfo;
- }
-}
diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts
deleted file mode 100644
index eea722aee..000000000
--- a/packages/subproviders/src/subproviders/nonce_tracker.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-import * as _ from 'lodash';
-
-import { BlockParamLiteral, JSONRPCRequestPayload } from 'ethereum-types';
-import EthereumTx = require('ethereumjs-tx');
-import ethUtil = require('ethereumjs-util');
-import providerEngineUtils = require('web3-provider-engine/util/rpc-cache-utils');
-
-import { Callback, ErrorCallback, NextCallback, NonceSubproviderErrors } from '../types';
-
-import { Subprovider } from './subprovider';
-
-const NONCE_TOO_LOW_ERROR_MESSAGE = 'Transaction nonce is 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 readonly _nonceCache: { [address: string]: string } = {};
- private static _reconstructTransaction(payload: JSONRPCRequestPayload): EthereumTx {
- const raw = payload.params[0];
- if (_.isUndefined(raw)) {
- throw new Error(NonceSubproviderErrors.EmptyParametersFound);
- }
- const rawData = ethUtil.toBuffer(raw);
- const transaction = new EthereumTx(rawData);
- return transaction;
- }
- private static _determineAddress(payload: JSONRPCRequestPayload): string {
- let address: string;
- switch (payload.method) {
- case 'eth_getTransactionCount':
- address = payload.params[0].toLowerCase();
- return address;
- case 'eth_sendRawTransaction':
- const transaction = NonceTrackerSubprovider._reconstructTransaction(payload);
- const addressRaw = transaction
- .getSenderAddress()
- .toString('hex')
- .toLowerCase();
- address = `0x${addressRaw}`;
- return address;
- default:
- throw new Error(NonceSubproviderErrors.CannotDetermineAddressFromPayload);
- }
- }
- /**
- * 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: JSONRPCRequestPayload, next: NextCallback, end: ErrorCallback): Promise<void> {
- switch (payload.method) {
- case 'eth_getTransactionCount':
- const requestDefaultBlock = providerEngineUtils.blockTagForPayload(payload);
- if (requestDefaultBlock === BlockParamLiteral.Pending) {
- const address = NonceTrackerSubprovider._determineAddress(payload);
- const cachedResult = this._nonceCache[address];
- if (!_.isUndefined(cachedResult)) {
- return end(null, cachedResult);
- } else {
- return next((requestError: Error | null, requestResult: any, cb: Callback) => {
- if (_.isNull(requestError)) {
- this._nonceCache[address] = requestResult as string;
- }
- cb();
- });
- }
- } else {
- return next();
- }
- case 'eth_sendRawTransaction':
- return next((sendTransactionError: Error | null, _txResult: any, cb: Callback) => {
- if (_.isNull(sendTransactionError)) {
- this._handleSuccessfulTransaction(payload);
- } else {
- this._handleSendTransactionError(payload, sendTransactionError);
- }
- cb();
- });
- default:
- return next();
- }
- }
- private _handleSuccessfulTransaction(payload: JSONRPCRequestPayload): void {
- const address = NonceTrackerSubprovider._determineAddress(payload);
- const transaction = NonceTrackerSubprovider._reconstructTransaction(payload);
- // Increment the nonce from the previous successfully submitted transaction
- let nonce = ethUtil.bufferToInt(transaction.nonce);
- nonce++;
- const hexBase = 16;
- let nextHexNonce = nonce.toString(hexBase);
- if (nextHexNonce.length % 2) {
- nextHexNonce = `0${nextHexNonce}`;
- }
- const nextPrefixedHexNonce = `0x${nextHexNonce}`;
- this._nonceCache[address] = nextPrefixedHexNonce;
- }
- private _handleSendTransactionError(payload: 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/private_key_wallet.ts b/packages/subproviders/src/subproviders/private_key_wallet.ts
deleted file mode 100644
index dca7e6810..000000000
--- a/packages/subproviders/src/subproviders/private_key_wallet.ts
+++ /dev/null
@@ -1,114 +0,0 @@
-import { assert } from '@0x/assert';
-import { EIP712TypedData } from '@0x/types';
-import { signTypedDataUtils } from '@0x/utils';
-import EthereumTx = require('ethereumjs-tx');
-import * as ethUtil from 'ethereumjs-util';
-import * as _ from 'lodash';
-
-import { PartialTxParams, WalletSubproviderErrors } from '../types';
-
-import { BaseWalletSubprovider } from './base_wallet_subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * This subprovider intercepts all account related RPC requests (e.g message/transaction signing, etc...) and handles
- * all requests with the supplied Ethereum private key.
- */
-export class PrivateKeyWalletSubprovider extends BaseWalletSubprovider {
- private readonly _address: string;
- private readonly _privateKeyBuffer: Buffer;
- /**
- * Instantiates a PrivateKeyWalletSubprovider.
- * @param privateKey The corresponding private key to an Ethereum address
- * @return PrivateKeyWalletSubprovider instance
- */
- constructor(privateKey: string) {
- assert.isString('privateKey', privateKey);
- super();
- this._privateKeyBuffer = Buffer.from(privateKey, 'hex');
- this._address = `0x${ethUtil.privateToAddress(this._privateKeyBuffer).toString('hex')}`;
- }
- /**
- * Retrieve the account associated with the supplied private key.
- * This method is implicitly called when issuing a `eth_accounts` JSON RPC request
- * via your providerEngine instance.
- * @return An array of accounts
- */
- public async getAccountsAsync(): Promise<string[]> {
- return [this._address];
- }
- /**
- * Sign a transaction with the private key. If you've added this Subprovider 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> {
- PrivateKeyWalletSubprovider._validateTxParams(txParams);
- if (!_.isUndefined(txParams.from) && txParams.from !== this._address) {
- throw new Error(
- `Requested to sign transaction with address: ${txParams.from}, instantiated with address: ${
- this._address
- }`,
- );
- }
- const tx = new EthereumTx(txParams);
- tx.sign(this._privateKeyBuffer);
- const rawTx = `0x${tx.serialize().toString('hex')}`;
- return rawTx;
- }
- /**
- * Sign a personal Ethereum signed message. The signing address will be calculated from the private key.
- * The address must be provided it must match the address calculated from the private key.
- * If you've added this Subprovider 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 Hex string message to sign
- * @param address Address of the account to sign with
- * @return Signature hex string (order: rsv)
- */
- public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- if (_.isUndefined(data)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isHexString('data', data);
- assert.isETHAddressHex('address', address);
- if (address !== this._address) {
- throw new Error(
- `Requested to sign message with address: ${address}, instantiated with address: ${this._address}`,
- );
- }
- const dataBuff = ethUtil.toBuffer(data);
- const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
- const sig = ethUtil.ecsign(msgHashBuff, this._privateKeyBuffer);
- const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s);
- return rpcSig;
- }
- /**
- * Sign an EIP712 Typed Data message. The signing address will be calculated from the private key.
- * The address must be provided it must match the address calculated from the private key.
- * If you've added this Subprovider to your app's provider, you can simply send an `eth_signTypedData`
- * 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 address Address of the account to sign with
- * @param data the typed data object
- * @return Signature hex string (order: rsv)
- */
- public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
- if (_.isUndefined(typedData)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignTypedData);
- }
- assert.isETHAddressHex('address', address);
- if (address !== this._address) {
- throw new Error(
- `Requested to sign message with address: ${address}, instantiated with address: ${this._address}`,
- );
- }
- const dataBuff = signTypedDataUtils.generateTypedDataHash(typedData);
- const sig = ethUtil.ecsign(dataBuff, this._privateKeyBuffer);
- const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s);
- return rpcSig;
- }
-}
diff --git a/packages/subproviders/src/subproviders/redundant_subprovider.ts b/packages/subproviders/src/subproviders/redundant_subprovider.ts
deleted file mode 100644
index 58312f203..000000000
--- a/packages/subproviders/src/subproviders/redundant_subprovider.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { promisify } from '@0x/utils';
-import { JSONRPCRequestPayload } from 'ethereum-types';
-import * as _ from 'lodash';
-
-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 RedundantSubprovider extends Subprovider {
- private readonly _subproviders: Subprovider[];
- private static async _firstSuccessAsync(
- subproviders: Subprovider[],
- payload: JSONRPCRequestPayload,
- next: Callback,
- ): Promise<any> {
- let lastErr: Error | undefined;
- for (const subprovider of subproviders) {
- try {
- const data = await promisify(subprovider.handleRequest.bind(subprovider))(payload, next);
- return data;
- } catch (err) {
- lastErr = err;
- continue;
- }
- }
- if (!_.isUndefined(lastErr)) {
- throw lastErr;
- }
- }
- /**
- * Instantiates a new RedundantSubprovider
- * @param subproviders Subproviders to attempt the request with
- */
- constructor(subproviders: Subprovider[]) {
- super();
- this._subproviders = subproviders;
- }
- /**
- * 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: JSONRPCRequestPayload,
- next: Callback,
- end: (err: Error | null, data?: any) => void,
- ): Promise<void> {
- const subprovidersCopy = this._subproviders.slice();
- try {
- const data = await RedundantSubprovider._firstSuccessAsync(subprovidersCopy, payload, next);
- end(null, data);
- } catch (err) {
- end(err);
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/rpc_subprovider.ts b/packages/subproviders/src/subproviders/rpc_subprovider.ts
deleted file mode 100644
index 437518e12..000000000
--- a/packages/subproviders/src/subproviders/rpc_subprovider.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import { assert } from '@0x/assert';
-import { StatusCodes } from '@0x/types';
-import { fetchAsync } from '@0x/utils';
-import { JSONRPCRequestPayload } from 'ethereum-types';
-import JsonRpcError = require('json-rpc-error');
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It forwards on JSON RPC requests to the supplied `rpcUrl` endpoint
- */
-export class RPCSubprovider extends Subprovider {
- private readonly _rpcUrl: string;
- private readonly _requestTimeoutMs: number;
- /**
- * @param rpcUrl URL to the backing Ethereum node to which JSON RPC requests should be sent
- * @param requestTimeoutMs Amount of miliseconds to wait before timing out the JSON RPC request
- */
- constructor(rpcUrl: string, requestTimeoutMs: number = 20000) {
- super();
- assert.isString('rpcUrl', rpcUrl);
- assert.isNumber('requestTimeoutMs', requestTimeoutMs);
- this._rpcUrl = rpcUrl;
- this._requestTimeoutMs = requestTimeoutMs;
- }
- /**
- * 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 async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, _next: Callback, end: ErrorCallback): Promise<void> {
- const finalPayload = Subprovider._createFinalPayload(payload);
- const headers = new Headers({
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- });
-
- let response;
- try {
- response = await fetchAsync(
- this._rpcUrl,
- {
- method: 'POST',
- headers,
- body: JSON.stringify(finalPayload),
- },
- this._requestTimeoutMs,
- );
- } catch (err) {
- end(new JsonRpcError.InternalError(err));
- return;
- }
-
- const text = await response.text();
- if (!response.ok) {
- const statusCode = response.status;
- switch (statusCode) {
- case StatusCodes.MethodNotAllowed:
- end(new JsonRpcError.MethodNotFound());
- return;
- case StatusCodes.GatewayTimeout:
- const errMsg =
- 'Gateway timeout. The request took too long to process. This can happen when querying logs over too wide a block range.';
- const err = new Error(errMsg);
- end(new JsonRpcError.InternalError(err));
- return;
- default:
- end(new JsonRpcError.InternalError(text));
- return;
- }
- }
-
- let data;
- try {
- data = JSON.parse(text);
- } catch (err) {
- end(new JsonRpcError.InternalError(err));
- return;
- }
-
- if (data.error) {
- end(data.error);
- return;
- }
- end(null, data.result);
- }
-}
diff --git a/packages/subproviders/src/subproviders/signer.ts b/packages/subproviders/src/subproviders/signer.ts
deleted file mode 100644
index 9bd5cbdf1..000000000
--- a/packages/subproviders/src/subproviders/signer.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import { marshaller, Web3Wrapper } from '@0x/web3-wrapper';
-import { JSONRPCRequestPayload, Provider } from 'ethereum-types';
-
-import { Callback, ErrorCallback } from '../types';
-
-import { Subprovider } from './subprovider';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine)
- * subprovider interface. It forwards JSON RPC requests involving the domain of a signer (getAccounts,
- * sendTransaction, signMessage etc...) to the provider instance supplied at instantiation. All other requests
- * are passed onwards for subsequent subproviders to handle.
- */
-export class SignerSubprovider extends Subprovider {
- private readonly _web3Wrapper: Web3Wrapper;
- /**
- * Instantiates a new SignerSubprovider.
- * @param provider Web3 provider that should handle all user account related requests
- */
- constructor(provider: Provider) {
- super();
- this._web3Wrapper = new Web3Wrapper(provider);
- }
- /**
- * 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 async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
- let message;
- let address;
- switch (payload.method) {
- case 'web3_clientVersion':
- try {
- const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
- end(null, nodeVersion);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_accounts':
- try {
- const accounts = await this._web3Wrapper.getAvailableAddressesAsync();
- end(null, accounts);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_sendTransaction':
- const [txParams] = payload.params;
- try {
- const txData = marshaller.unmarshalTxData(txParams);
- const txHash = await this._web3Wrapper.sendTransactionAsync(txData);
- end(null, txHash);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_sign':
- [address, message] = payload.params;
- try {
- const signature = await this._web3Wrapper.signMessageAsync(address, message);
- end(null, signature);
- } catch (err) {
- end(err);
- }
- return;
- case 'eth_signTypedData':
- [address, message] = payload.params;
- try {
- const signature = await this._web3Wrapper.signTypedDataAsync(address, message);
- end(null, signature);
- } catch (err) {
- end(err);
- }
- return;
- default:
- next();
- return;
- }
- }
-}
diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts
deleted file mode 100644
index cd6780e0c..000000000
--- a/packages/subproviders/src/subproviders/subprovider.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { promisify } from '@0x/utils';
-import { JSONRPCRequestPayload, JSONRPCResponsePayload, Provider } from 'ethereum-types';
-
-import { Callback, ErrorCallback, 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.
- */
-export abstract class Subprovider {
- // tslint:disable-next-line:underscore-private-and-protected
- private engine!: Provider;
- protected static _createFinalPayload(
- payload: Partial<JSONRPCRequestPayloadWithMethod>,
- ): Partial<JSONRPCRequestPayloadWithMethod> {
- const finalPayload = {
- // defaults
- id: Subprovider._getRandomId(),
- jsonrpc: '2.0',
- params: [],
- ...payload,
- };
- return finalPayload;
- }
- // Ported from: https://github.com/MetaMask/provider-engine/blob/master/util/random-id.js
- private static _getRandomId(): number {
- const extraDigits = 3;
- const baseTen = 10;
- // 13 time digits
- const datePart = new Date().getTime() * Math.pow(baseTen, extraDigits);
- // 3 random digits
- const extraPart = Math.floor(Math.random() * Math.pow(baseTen, extraDigits));
- // 16 digits
- return datePart + extraPart;
- }
- /**
- * @param payload JSON RPC request payload
- * @param next A callback to pass the request to the next subprovider in the stack
- * @param end A callback called once the subprovider is done handling the request
- */
- // tslint:disable-next-line:async-suffix
- public abstract async handleRequest(
- payload: JSONRPCRequestPayload,
- next: Callback,
- end: ErrorCallback,
- ): Promise<void>;
-
- /**
- * 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<JSONRPCRequestPayloadWithMethod>): Promise<JSONRPCResponsePayload> {
- const finalPayload = Subprovider._createFinalPayload(payload);
- // Promisify does the binding internally and `this` is supplied as a second argument
- // tslint:disable-next-line:no-unbound-method
- const response = await promisify<JSONRPCResponsePayload>(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.
- * @param engine The ProviderEngine this subprovider is added to
- */
- public setEngine(engine: Provider): void {
- this.engine = engine;
- }
-}
diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts
deleted file mode 100644
index ed3aea176..000000000
--- a/packages/subproviders/src/types.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-import { ECSignature } from '@0x/types';
-import { JSONRPCRequestPayload } from 'ethereum-types';
-import HDNode = require('hdkey');
-
-export interface LedgerCommunicationClient {
- close: () => Promise<void>;
-}
-
-/**
- * Elliptic Curve signature
- * The LedgerEthereumClient sends Ethereum-specific requests to the Ledger Nano S
- * It uses an internal LedgerCommunicationClient to relay these requests. Currently
- * NodeJs and Browser communication are supported.
- */
-export interface LedgerEthereumClient {
- // shouldGetChainCode is defined as `true` instead of `boolean` because other types rely on the assumption
- // that we get back the chain code and we don't have dependent types to express it properly
- getAddress: (
- derivationPath: string,
- askForDeviceConfirmation: boolean,
- shouldGetChainCode: true,
- ) => Promise<LedgerGetAddressResult>;
- signTransaction: (derivationPath: string, rawTxHex: string) => Promise<ECSignatureString>;
- signPersonalMessage: (derivationPath: string, messageHex: string) => Promise<ECSignature>;
- transport: LedgerCommunicationClient;
-}
-
-export interface ECSignatureString {
- v: string;
- r: string;
- s: string;
-}
-
-export type LedgerEthereumClientFactoryAsync = () => Promise<LedgerEthereumClient>;
-
-/**
- * networkId: The ethereum networkId to set as the chainId from EIP155
- * ledgerConnectionType: Environment in which you wish to connect to Ledger (nodejs or browser)
- * derivationPath: Initial derivation path to use e.g 44'/60'/0'
- * accountFetchingConfigs: configs related to fetching accounts from a Ledger
- */
-export interface LedgerSubproviderConfigs {
- networkId: number;
- ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync;
- baseDerivationPath?: string;
- accountFetchingConfigs?: AccountFetchingConfigs;
-}
-
-/**
- * addressSearchLimit: The maximum number of addresses to search through, defaults to 1000
- * numAddressesToReturn: Number of addresses to return from 'eth_accounts' call
- * shouldAskForOnDeviceConfirmation: Whether you wish to prompt the user on their Ledger
- * before fetching their addresses
- */
-export interface AccountFetchingConfigs {
- addressSearchLimit?: number;
- numAddressesToReturn?: number;
- shouldAskForOnDeviceConfirmation?: boolean;
-}
-
-/**
- * mnemonic: The string mnemonic seed
- * addressSearchLimit: The maximum number of addresses to search through, defaults to 1000
- * baseDerivationPath: The base derivation path (e.g 44'/60'/0'/0)
- */
-export interface MnemonicWalletSubproviderConfigs {
- mnemonic: string;
- addressSearchLimit?: number;
- baseDerivationPath?: string;
-}
-
-export interface SignatureData {
- hash: string;
- r: string;
- s: string;
- v: number;
-}
-
-export interface LedgerGetAddressResult {
- address: string;
- publicKey: string;
- chainCode: string;
-}
-
-export interface PartialTxParams {
- nonce: string;
- gasPrice?: string;
- gas: string;
- to: string;
- from: string;
- value?: string;
- data?: string;
- chainId: number; // EIP 155 chainId - mainnet: 1, ropsten: 3
-}
-
-export type DoneCallback = (err?: Error) => void;
-
-export interface LedgerCommunication {
- close_async: () => Promise<void>;
-}
-
-export interface ResponseWithTxParams {
- raw: string;
- tx: PartialTxParams;
-}
-
-export enum WalletSubproviderErrors {
- AddressNotFound = 'ADDRESS_NOT_FOUND',
- DataMissingForSignPersonalMessage = 'DATA_MISSING_FOR_SIGN_PERSONAL_MESSAGE',
- DataMissingForSignTypedData = 'DATA_MISSING_FOR_SIGN_TYPED_DATA',
- SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED',
- FromAddressMissingOrInvalid = 'FROM_ADDRESS_MISSING_OR_INVALID',
- MethodNotSupported = 'METHOD_NOT_SUPPORTED',
-}
-export enum LedgerSubproviderErrors {
- TooOldLedgerFirmware = 'TOO_OLD_LEDGER_FIRMWARE',
- MultipleOpenConnectionsDisallowed = 'MULTIPLE_OPEN_CONNECTIONS_DISALLOWED',
-}
-
-export enum NonceSubproviderErrors {
- EmptyParametersFound = 'EMPTY_PARAMETERS_FOUND',
- CannotDetermineAddressFromPayload = 'CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD',
-}
-export interface DerivedHDKeyInfo {
- address: string;
- baseDerivationPath: string;
- derivationPath: string;
- hdKey: HDNode;
-}
-
-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 JSONRPCRequestPayload {
- method: string;
-}
diff --git a/packages/subproviders/src/utils/subprovider_utils.ts b/packages/subproviders/src/utils/subprovider_utils.ts
deleted file mode 100644
index beda408ab..000000000
--- a/packages/subproviders/src/utils/subprovider_utils.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import Web3ProviderEngine = require('web3-provider-engine');
-
-import { Subprovider } from '../subproviders/subprovider';
-
-/**
- * Prepends a subprovider to a provider
- * @param provider Given provider
- * @param subprovider Subprovider to prepend
- */
-export function prependSubprovider(provider: Web3ProviderEngine, subprovider: Subprovider): void {
- subprovider.setEngine(provider);
- // HACK: We use implementation details of provider engine here
- // https://github.com/MetaMask/provider-engine/blob/master/index.js#L68
- (provider as any)._providers = [subprovider, ...(provider as any)._providers];
-}
diff --git a/packages/subproviders/src/utils/wallet_utils.ts b/packages/subproviders/src/utils/wallet_utils.ts
deleted file mode 100644
index 7027ca8a0..000000000
--- a/packages/subproviders/src/utils/wallet_utils.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import ethUtil = require('ethereumjs-util');
-import HDNode = require('hdkey');
-
-import { DerivedHDKeyInfo } from '../types';
-
-const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000;
-
-class DerivedHDKeyInfoIterator implements IterableIterator<DerivedHDKeyInfo> {
- private readonly _parentDerivedKeyInfo: DerivedHDKeyInfo;
- private readonly _searchLimit: number;
- private _index: number;
-
- constructor(initialDerivedKey: DerivedHDKeyInfo, searchLimit: number = DEFAULT_ADDRESS_SEARCH_LIMIT) {
- this._searchLimit = searchLimit;
- this._parentDerivedKeyInfo = initialDerivedKey;
- this._index = 0;
- }
-
- public next(): IteratorResult<DerivedHDKeyInfo> {
- const baseDerivationPath = this._parentDerivedKeyInfo.baseDerivationPath;
- const derivationIndex = this._index;
- const fullDerivationPath = `m/${baseDerivationPath}/${derivationIndex}`;
- const path = `m/${derivationIndex}`;
- const hdKey = this._parentDerivedKeyInfo.hdKey.derive(path);
- const address = walletUtils.addressOfHDKey(hdKey);
- const derivedKey: DerivedHDKeyInfo = {
- address,
- hdKey,
- baseDerivationPath,
- derivationPath: fullDerivationPath,
- };
- const isDone = this._index === this._searchLimit;
- this._index++;
- return {
- done: isDone,
- value: derivedKey,
- };
- }
-
- public [Symbol.iterator](): IterableIterator<DerivedHDKeyInfo> {
- return this;
- }
-}
-
-export const walletUtils = {
- calculateDerivedHDKeyInfos(parentDerivedKeyInfo: DerivedHDKeyInfo, numberOfKeys: number): DerivedHDKeyInfo[] {
- const derivedKeys: DerivedHDKeyInfo[] = [];
- const derivedKeyIterator = new DerivedHDKeyInfoIterator(parentDerivedKeyInfo, numberOfKeys);
- for (const key of derivedKeyIterator) {
- derivedKeys.push(key);
- }
- return derivedKeys;
- },
- findDerivedKeyInfoForAddressIfExists(
- address: string,
- parentDerivedKeyInfo: DerivedHDKeyInfo,
- searchLimit: number,
- ): DerivedHDKeyInfo | undefined {
- const lowercaseAddress = address.toLowerCase();
- let matchedKey: DerivedHDKeyInfo | undefined;
- const derivedKeyIterator = new DerivedHDKeyInfoIterator(parentDerivedKeyInfo, searchLimit);
- for (const key of derivedKeyIterator) {
- if (key.address === lowercaseAddress) {
- matchedKey = key;
- break;
- }
- }
- return matchedKey;
- },
- addressOfHDKey(hdKey: HDNode): string {
- const shouldSanitizePublicKey = true;
- const derivedPublicKey = hdKey.publicKey;
- const ethereumAddressUnprefixed = ethUtil
- .publicToAddress(derivedPublicKey, shouldSanitizePublicKey)
- .toString('hex');
- const address = ethUtil.addHexPrefix(ethereumAddressUnprefixed).toLowerCase();
- return address;
- },
-};