diff options
author | Fabio Berger <me@fabioberger.com> | 2018-03-14 21:16:08 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-03-14 21:16:08 +0800 |
commit | 009b70f5b218a1ccb154034936256308131b7d9c (patch) | |
tree | cd9642a8d3323c9e80da54ac4e8fc40ade9f9020 /packages/subproviders/src | |
parent | f7c1e10b5ac112866ee55e7fededdb37c890d30f (diff) | |
parent | 3f3e8be004818ddaa1921b3dff12bdd46052278b (diff) | |
download | dexon-sol-tools-009b70f5b218a1ccb154034936256308131b7d9c.tar dexon-sol-tools-009b70f5b218a1ccb154034936256308131b7d9c.tar.gz dexon-sol-tools-009b70f5b218a1ccb154034936256308131b7d9c.tar.bz2 dexon-sol-tools-009b70f5b218a1ccb154034936256308131b7d9c.tar.lz dexon-sol-tools-009b70f5b218a1ccb154034936256308131b7d9c.tar.xz dexon-sol-tools-009b70f5b218a1ccb154034936256308131b7d9c.tar.zst dexon-sol-tools-009b70f5b218a1ccb154034936256308131b7d9c.zip |
Merge branch 'development' into convertScriptsToTs
* development: (71 commits)
Transform input data before encoding for callAsync and getABIEncodedTransactionData
Update coverage badge to show development coverage
Configure post build hook
Notify coveralls after all tasks have finished
Address feedback
Revert "Report all coverage reports together"
Separate published packages and typescript typings on README
Report all coverage reports together
Add other statement types
Properly and consistently parse ENV vars
Add forgotten file
Start using solidity-parser-antlr
Fix the default always overriding to address
Submit a TD PR
Add an explanatory comment for making ranges unique
Fix a typo in handling env variables
Introduce TESTRPC_FIRST_ADDRESS
Make BlockchainLifecycle accept only web3Wrapper
Fix comments
Fix deployer CHANGELOG
...
# Conflicts:
# README.md
# packages/deployer/package.json
# packages/subproviders/src/globals.d.ts
# yarn.lock
Diffstat (limited to 'packages/subproviders/src')
11 files changed, 114 insertions, 79 deletions
diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index e51801b5c..b3dcd4ed3 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -67,16 +67,6 @@ declare module '@ledgerhq/hw-transport-node-hid' { } } -// Semaphore-async-await declarations -declare module 'semaphore-async-await' { - class Semaphore { - constructor(permits: number); - public wait(): Promise<void>; - public signal(): void; - } - export default Semaphore; -} - // web3-provider-engine declarations declare module 'web3-provider-engine/subproviders/subprovider' { class Subprovider {} @@ -141,3 +131,18 @@ declare module '*.json' { export default json; /* tslint:enable */ } + +// ganache-core declarations +declare module 'ganache-core' { + import * as Web3 from 'web3'; + export interface GanacheOpts { + verbose: boolean; + logger: { + log(msg: string): void; + }; + port: number; + networkId: number; + mnemonic: string; + } + export function provider(opts: GanacheOpts): Web3.Provider; +} diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts index e22b6f5f3..cafb50fe5 100644 --- a/packages/subproviders/src/index.ts +++ b/packages/subproviders/src/index.ts @@ -2,12 +2,15 @@ import Eth from '@ledgerhq/hw-app-eth'; import TransportU2F from '@ledgerhq/hw-transport-u2f'; import { LedgerEthereumClient } from './types'; +export { Callback, NextCallback } from './types'; export { EmptyWalletSubprovider } from './subproviders/empty_wallet_subprovider'; export { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_subprovider'; export { InjectedWeb3Subprovider } from './subproviders/injected_web3'; export { RedundantRPCSubprovider } from './subproviders/redundant_rpc'; export { LedgerSubprovider } from './subproviders/ledger'; +export { GanacheSubprovider } from './subproviders/ganache'; +export { Subprovider } from './subproviders/subprovider'; export { NonceTrackerSubprovider } from './subproviders/nonce_tracker'; export { ECSignature, LedgerWalletSubprovider, LedgerCommunicationClient, NonceSubproviderErrors } from './types'; diff --git a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts index 8c1fdfdb2..f5983dd9b 100644 --- a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts +++ b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts @@ -1,14 +1,20 @@ -import { JSONRPCPayload } from '@0xproject/types'; +import * as Web3 from 'web3'; + +import { Subprovider } from './subprovider'; /* * This class implements the web3-provider-engine subprovider interface and returns * that the provider has no addresses when queried. * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js */ -export class EmptyWalletSubprovider { +export class EmptyWalletSubprovider extends Subprovider { // This method needs to be here to satisfy the interface but linter wants it to be static. // tslint:disable-next-line:prefer-function-over-method - public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error | null, result: any) => void) { + public handleRequest( + payload: Web3.JSONRPCRequestPayload, + next: () => void, + end: (err: Error | null, result: any) => void, + ) { switch (payload.method) { case 'eth_accounts': end(null, []); @@ -19,9 +25,4 @@ export class EmptyWalletSubprovider { return; } } - // Required to implement this method despite not needing it for this subprovider - // tslint:disable-next-line:prefer-function-over-method - public setEngine(engine: any) { - // noop - } } diff --git a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts index b455a0ed7..2421dcd02 100644 --- a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts +++ b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts @@ -1,4 +1,6 @@ -import { JSONRPCPayload } from '@0xproject/types'; +import * as Web3 from 'web3'; + +import { Subprovider } from './subprovider'; /* * This class implements the web3-provider-engine subprovider interface and returns @@ -8,14 +10,19 @@ import { JSONRPCPayload } from '@0xproject/types'; * Source: https://github.com/trufflesuite/ganache-cli/issues/437 * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js */ -export class FakeGasEstimateSubprovider { +export class FakeGasEstimateSubprovider extends Subprovider { private _constantGasAmount: number; constructor(constantGasAmount: number) { + super(); this._constantGasAmount = constantGasAmount; } // This method needs to be here to satisfy the interface but linter wants it to be static. // tslint:disable-next-line:prefer-function-over-method - public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error | null, result: any) => void) { + public handleRequest( + payload: Web3.JSONRPCRequestPayload, + next: () => void, + end: (err: Error | null, result: any) => void, + ) { switch (payload.method) { case 'eth_estimateGas': end(null, this._constantGasAmount); @@ -26,9 +33,4 @@ export class FakeGasEstimateSubprovider { return; } } - // Required to implement this method despite not needing it for this subprovider - // tslint:disable-next-line:prefer-function-over-method - public setEngine(engine: any) { - // noop - } } diff --git a/packages/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts new file mode 100644 index 000000000..a979aecf4 --- /dev/null +++ b/packages/subproviders/src/subproviders/ganache.ts @@ -0,0 +1,28 @@ +import * as Ganache from 'ganache-core'; +import * as Web3 from 'web3'; + +import { Subprovider } from './subprovider'; + +/* + * This class implements the web3-provider-engine subprovider interface and returns + * the provider connected to a in-process ganache. + * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js + */ +export class GanacheSubprovider extends Subprovider { + private _ganacheProvider: Web3.Provider; + constructor(opts: any) { + super(); + this._ganacheProvider = Ganache.provider(opts); + } + // This method needs to be here to satisfy the interface but linter wants it to be static. + // tslint:disable-next-line:prefer-function-over-method + public handleRequest( + payload: Web3.JSONRPCRequestPayload, + next: () => void, + end: (err: Error | null, result: any) => void, + ) { + this._ganacheProvider.sendAsync(payload, (err: Error | null, result: any) => { + end(err, result && result.result); + }); + } +} diff --git a/packages/subproviders/src/subproviders/injected_web3.ts b/packages/subproviders/src/subproviders/injected_web3.ts index 0d70180c4..6d4e2b27b 100644 --- a/packages/subproviders/src/subproviders/injected_web3.ts +++ b/packages/subproviders/src/subproviders/injected_web3.ts @@ -1,5 +1,7 @@ import * as _ from 'lodash'; -import Web3 = require('web3'); +import * as Web3 from 'web3'; + +import { Subprovider } from './subprovider'; /* * This class implements the web3-provider-engine subprovider interface and forwards @@ -7,9 +9,10 @@ import Web3 = require('web3'); * provider instance in their browser. * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js */ -export class InjectedWeb3Subprovider { +export class InjectedWeb3Subprovider extends Subprovider { private _injectedWeb3: Web3; constructor(subprovider: Web3.Provider) { + super(); this._injectedWeb3 = new Web3(subprovider); } public handleRequest( @@ -40,11 +43,4 @@ export class InjectedWeb3Subprovider { return; } } - // Required to implement this method despite not needing it for this subprovider - // The engine argument type should be Web3ProviderEngine, but we've decided to keep it as type any - // to remove the provider engine depdency given this method is a noop - // tslint:disable-next-line:prefer-function-over-method - public setEngine(engine: any) { - // noop - } } diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 0a84caae3..b67b49bee 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -4,8 +4,8 @@ import EthereumTx = require('ethereumjs-tx'); import ethUtil = require('ethereumjs-util'); import HDNode = require('hdkey'); import * as _ from 'lodash'; -import Semaphore from 'semaphore-async-await'; -import Web3 = require('web3'); +import { Lock } from 'semaphore-async-await'; +import * as Web3 from 'web3'; import { LedgerEthereumClient, @@ -24,8 +24,8 @@ const ASK_FOR_ON_DEVICE_CONFIRMATION = false; const SHOULD_GET_CHAIN_CODE = true; export class LedgerSubprovider extends Subprovider { - private _nonceLock: Semaphore; - private _connectionLock: Semaphore; + private _nonceLock = new Lock(); + private _connectionLock = new Lock(); private _networkId: number; private _derivationPath: string; private _derivationPathIndex: number; @@ -39,8 +39,6 @@ export class LedgerSubprovider extends Subprovider { } constructor(config: LedgerSubproviderConfigs) { super(); - this._nonceLock = new Semaphore(1); - this._connectionLock = new Semaphore(1); this._networkId = config.networkId; this._ledgerEthereumClientFactoryAsync = config.ledgerEthereumClientFactoryAsync; this._derivationPath = config.derivationPath || DEFAULT_DERIVATION_PATH; @@ -147,7 +145,7 @@ export class LedgerSubprovider extends Subprovider { hdKey.publicKey = new Buffer(ledgerResponse.publicKey, 'hex'); hdKey.chainCode = new Buffer(ledgerResponse.chainCode, 'hex'); - const accounts = []; + const accounts: string[] = []; for (let i = 0; i < numberOfAccounts; i++) { const derivedHDNode = hdKey.derive(`m/${i + this._derivationPathIndex}`); const derivedPublicKey = derivedHDNode.publicKey; @@ -221,27 +219,27 @@ export class LedgerSubprovider extends Subprovider { return derivationPath; } private async _createLedgerClientAsync(): Promise<LedgerEthereumClient> { - await this._connectionLock.wait(); + await this._connectionLock.acquire(); if (!_.isUndefined(this._ledgerClientIfExists)) { - this._connectionLock.signal(); + this._connectionLock.release(); throw new Error(LedgerSubproviderErrors.MultipleOpenConnectionsDisallowed); } const ledgerEthereumClient = await this._ledgerEthereumClientFactoryAsync(); - this._connectionLock.signal(); + this._connectionLock.release(); return ledgerEthereumClient; } private async _destroyLedgerClientAsync() { - await this._connectionLock.wait(); + await this._connectionLock.acquire(); if (_.isUndefined(this._ledgerClientIfExists)) { - this._connectionLock.signal(); + this._connectionLock.release(); return; } await this._ledgerClientIfExists.transport.close(); this._ledgerClientIfExists = undefined; - this._connectionLock.signal(); + this._connectionLock.release(); } private async _sendTransactionAsync(txParams: PartialTxParams): Promise<string> { - await this._nonceLock.wait(); + await this._nonceLock.acquire(); try { // fill in the extras const filledParams = await this._populateMissingTxParamsAsync(txParams); @@ -253,29 +251,29 @@ export class LedgerSubprovider extends Subprovider { params: [signedTx], }; const result = await this.emitPayloadAsync(payload); - this._nonceLock.signal(); + this._nonceLock.release(); return result.result; } catch (err) { - this._nonceLock.signal(); + this._nonceLock.release(); throw err; } } private async _signTransactionWithoutSendingAsync(txParams: PartialTxParams): Promise<ResponseWithTxParams> { - await this._nonceLock.wait(); + await this._nonceLock.acquire(); try { // fill in the extras const filledParams = await this._populateMissingTxParamsAsync(txParams); // sign it const signedTx = await this.signTransactionAsync(filledParams); - this._nonceLock.signal(); + this._nonceLock.release(); const result = { raw: signedTx, tx: txParams, }; return result; } catch (err) { - this._nonceLock.signal(); + this._nonceLock.release(); throw err; } } diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts index d967d40f2..82eab4a9a 100644 --- a/packages/subproviders/src/subproviders/nonce_tracker.ts +++ b/packages/subproviders/src/subproviders/nonce_tracker.ts @@ -1,12 +1,12 @@ import * as _ from 'lodash'; +import { BlockParamLiteral } from '@0xproject/types'; import EthereumTx = require('ethereumjs-tx'); import ethUtil = require('ethereumjs-util'); +import * as Web3 from 'web3'; import providerEngineUtils = require('web3-provider-engine/util/rpc-cache-utils'); -import { BlockParamLiteral } from '@0xproject/types'; - -import { ErrorCallback, JSONRPCPayload, NonceSubproviderErrors, OptionalNextCallback } from '../types'; +import { Callback, ErrorCallback, NextCallback, NonceSubproviderErrors } from '../types'; import { Subprovider } from './subprovider'; @@ -19,7 +19,7 @@ const NONCE_TOO_LOW_ERROR_MESSAGE = 'Transaction nonce is too low'; */ export class NonceTrackerSubprovider extends Subprovider { private _nonceCache: { [address: string]: string } = {}; - private static _reconstructTransaction(payload: JSONRPCPayload): EthereumTx { + private static _reconstructTransaction(payload: Web3.JSONRPCRequestPayload): EthereumTx { const raw = payload.params[0]; if (_.isUndefined(raw)) { throw new Error(NonceSubproviderErrors.EmptyParametersFound); @@ -28,7 +28,7 @@ export class NonceTrackerSubprovider extends Subprovider { const transaction = new EthereumTx(rawData); return transaction; } - private static _determineAddress(payload: JSONRPCPayload): string { + private static _determineAddress(payload: Web3.JSONRPCRequestPayload): string { let address: string; switch (payload.method) { case 'eth_getTransactionCount': @@ -48,7 +48,11 @@ export class NonceTrackerSubprovider extends Subprovider { } // Required to implement this public interface which doesn't conform to our linting rule. // tslint:disable-next-line:async-suffix - public async handleRequest(payload: JSONRPCPayload, next: OptionalNextCallback, end: ErrorCallback): Promise<void> { + public async handleRequest( + payload: Web3.JSONRPCRequestPayload, + next: NextCallback, + end: ErrorCallback, + ): Promise<void> { switch (payload.method) { case 'eth_getTransactionCount': const requestDefaultBlock = providerEngineUtils.blockTagForPayload(payload); @@ -58,7 +62,7 @@ export class NonceTrackerSubprovider extends Subprovider { if (!_.isUndefined(cachedResult)) { return end(null, cachedResult); } else { - return next((requestError: Error | null, requestResult: any, cb: any) => { + return next((requestError: Error | null, requestResult: any, cb: Callback) => { if (_.isNull(requestError)) { this._nonceCache[address] = requestResult as string; } @@ -69,7 +73,7 @@ export class NonceTrackerSubprovider extends Subprovider { return next(); } case 'eth_sendRawTransaction': - return next((sendTransactionError: Error | null, txResult: any, cb: any) => { + return next((sendTransactionError: Error | null, txResult: any, cb: Callback) => { if (_.isNull(sendTransactionError)) { this._handleSuccessfulTransaction(payload); } else { @@ -81,7 +85,7 @@ export class NonceTrackerSubprovider extends Subprovider { return next(); } } - private _handleSuccessfulTransaction(payload: JSONRPCPayload): void { + private _handleSuccessfulTransaction(payload: Web3.JSONRPCRequestPayload): void { const address = NonceTrackerSubprovider._determineAddress(payload); const transaction = NonceTrackerSubprovider._reconstructTransaction(payload); // Increment the nonce from the previous successfully submitted transaction @@ -94,7 +98,7 @@ export class NonceTrackerSubprovider extends Subprovider { const nextPrefixedHexNonce = `0x${nextHexNonce}`; this._nonceCache[address] = nextPrefixedHexNonce; } - private _handleSendTransactionError(payload: JSONRPCPayload, err: Error): void { + private _handleSendTransactionError(payload: Web3.JSONRPCRequestPayload, err: Error): void { const address = NonceTrackerSubprovider._determineAddress(payload); if (this._nonceCache[address] && _.includes(err.message, NONCE_TOO_LOW_ERROR_MESSAGE)) { delete this._nonceCache[address]; diff --git a/packages/subproviders/src/subproviders/redundant_rpc.ts b/packages/subproviders/src/subproviders/redundant_rpc.ts index 5a94f93d7..0df2f91f4 100644 --- a/packages/subproviders/src/subproviders/redundant_rpc.ts +++ b/packages/subproviders/src/subproviders/redundant_rpc.ts @@ -1,16 +1,15 @@ import { promisify } from '@0xproject/utils'; import * as _ from 'lodash'; +import * as Web3 from 'web3'; import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); -import { JSONRPCPayload } from '../types'; - import { Subprovider } from './subprovider'; export class RedundantRPCSubprovider extends Subprovider { private _rpcs: RpcSubprovider[]; private static async _firstSuccessAsync( rpcs: RpcSubprovider[], - payload: JSONRPCPayload, + payload: Web3.JSONRPCRequestPayload, next: () => void, ): Promise<any> { let lastErr: Error | undefined; @@ -38,7 +37,7 @@ export class RedundantRPCSubprovider extends Subprovider { // Required to implement this public interface which doesn't conform to our linting rule. // tslint:disable-next-line:async-suffix public async handleRequest( - payload: JSONRPCPayload, + payload: Web3.JSONRPCRequestPayload, next: () => void, end: (err: Error | null, data?: any) => void, ): Promise<void> { diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts index 6435c9f65..d4e0de67a 100644 --- a/packages/subproviders/src/subproviders/subprovider.ts +++ b/packages/subproviders/src/subproviders/subprovider.ts @@ -1,7 +1,5 @@ import promisify = require('es6-promisify'); -import Web3 = require('web3'); - -import { JSONRPCPayload } from '../types'; +import * as Web3 from 'web3'; /* * A version of the base class Subprovider found in providerEngine * This one has an async/await `emitPayloadAsync` and also defined types. @@ -19,7 +17,9 @@ export class Subprovider { // 16 digits return datePart + extraPart; } - private static _createFinalPayload(payload: JSONRPCPayload): Web3.JSONRPCRequestPayload { + private static _createFinalPayload( + payload: Partial<Web3.JSONRPCRequestPayload> & { method: string }, + ): Web3.JSONRPCRequestPayload { const finalPayload = { // defaults id: Subprovider._getRandomId(), @@ -32,7 +32,9 @@ export class Subprovider { public setEngine(engine: any): void { this._engine = engine; } - public async emitPayloadAsync(payload: JSONRPCPayload): Promise<any> { + public async emitPayloadAsync( + payload: Partial<Web3.JSONRPCRequestPayload> & { method: string }, + ): Promise<Web3.JSONRPCResponsePayload> { const finalPayload = Subprovider._createFinalPayload(payload); const response = await promisify(this._engine.sendAsync, this._engine)(finalPayload); return response; diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts index f49ac6107..543da5947 100644 --- a/packages/subproviders/src/types.ts +++ b/packages/subproviders/src/types.ts @@ -91,11 +91,6 @@ export interface PartialTxParams { export type DoneCallback = (err?: Error) => void; -export interface JSONRPCPayload { - params: any[]; - method: string; -} - export interface LedgerCommunication { close_async: () => Promise<void>; } @@ -118,5 +113,7 @@ export enum NonceSubproviderErrors { CannotDetermineAddressFromPayload = 'CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD', } -export type OptionalNextCallback = (callback?: (err: Error | null, result: any, cb: any) => void) => void; export type ErrorCallback = (err: Error | null, data?: any) => void; +export type Callback = () => void; +export type OnNextCompleted = (err: Error | null, result: any, cb: Callback) => void; +export type NextCallback = (callback?: OnNextCompleted) => void; |