diff options
author | Fabio Berger <me@fabioberger.com> | 2018-09-25 21:59:37 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-25 21:59:37 +0800 |
commit | 7570f3db513f1b728e27cdd6273642ab999adbcc (patch) | |
tree | a4c7c16da62f7c3aed4321927d8ef16fc5d23eeb /packages | |
parent | 78ef98c27ce954f7e46b261b0809ff9d8d70519b (diff) | |
parent | 977d55c61b9ba8979e0846a780cd8020c821df9b (diff) | |
download | dexon-sol-tools-7570f3db513f1b728e27cdd6273642ab999adbcc.tar dexon-sol-tools-7570f3db513f1b728e27cdd6273642ab999adbcc.tar.gz dexon-sol-tools-7570f3db513f1b728e27cdd6273642ab999adbcc.tar.bz2 dexon-sol-tools-7570f3db513f1b728e27cdd6273642ab999adbcc.tar.lz dexon-sol-tools-7570f3db513f1b728e27cdd6273642ab999adbcc.tar.xz dexon-sol-tools-7570f3db513f1b728e27cdd6273642ab999adbcc.tar.zst dexon-sol-tools-7570f3db513f1b728e27cdd6273642ab999adbcc.zip |
Merge pull request #1080 from 0xProject/upgradeBlockstream
Fix dropped events issue in Order-watcher and Contract-wrappers subscriptions
Diffstat (limited to 'packages')
-rw-r--r-- | packages/contract-wrappers/CHANGELOG.json | 23 | ||||
-rw-r--r-- | packages/contract-wrappers/package.json | 2 | ||||
-rw-r--r-- | packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts | 47 | ||||
-rw-r--r-- | packages/ethereum-types/src/index.ts | 1 | ||||
-rw-r--r-- | packages/order-watcher/CHANGELOG.json | 23 | ||||
-rw-r--r-- | packages/order-watcher/package.json | 2 | ||||
-rw-r--r-- | packages/order-watcher/src/order_watcher/event_watcher.ts | 49 | ||||
-rw-r--r-- | packages/web3-wrapper/CHANGELOG.json | 5 | ||||
-rw-r--r-- | packages/web3-wrapper/src/web3_wrapper.ts | 79 |
9 files changed, 157 insertions, 74 deletions
diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index 65aaf15c7..d3e0ad5d1 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,21 +1,36 @@ [ { - "timestamp": 1537875740, + "version": "2.0.0", + "changes": [ + { + "note": + "Fixes dropped events in subscriptions by fetching logs by blockHash instead of blockNumber. Support for fetching by blockHash was added in Geth > v1.8.13 and Parity > v2.1.0. Infura works too.", + "pr": 1080 + }, + { + "note": + "Fix misunderstanding about blockstream interface callbacks and pass the raw JSON RPC responses to it", + "pr": 1080 + } + ] + }, + { "version": "1.0.5", "changes": [ { "note": "Dependencies updated" } - ] + ], + "timestamp": 1537875740 }, { - "timestamp": 1537541580, "version": "1.0.4", "changes": [ { "note": "Dependencies updated" } - ] + ], + "timestamp": 1537541580 }, { "version": "1.0.3", diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index 544d667c6..57f994ff1 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -82,7 +82,7 @@ "@0xproject/utils": "^1.0.10", "@0xproject/web3-wrapper": "^3.0.0", "ethereum-types": "^1.0.7", - "ethereumjs-blockstream": "5.0.0", + "ethereumjs-blockstream": "6.0.0", "ethereumjs-util": "^5.1.1", "ethers": "3.0.22", "js-sha3": "^0.7.0", diff --git a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts index 19a882712..f7a89e3be 100644 --- a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts @@ -1,14 +1,14 @@ import { AbiDecoder, intervalUtils, logUtils } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import { marshaller, Web3Wrapper } from '@0xproject/web3-wrapper'; import { BlockParamLiteral, - BlockWithoutTransactionData, ContractAbi, ContractArtifact, FilterObject, LogEntry, LogWithDecodedArgs, RawLog, + RawLogEntry, } from 'ethereum-types'; import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream'; import * as _ from 'lodash'; @@ -158,7 +158,8 @@ export abstract class ContractWrapper { return addressIfExists; } } - private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, log: LogEntry): void { + private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, rawLog: RawLogEntry): void { + const log: LogEntry = marshaller.unmarshalLog(rawLog); _.forEach(this._filters, (filter: FilterObject, filterToken: string) => { if (filterUtils.matchesFilter(log, filter)) { const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>; @@ -175,8 +176,8 @@ export abstract class ContractWrapper { throw new Error(ContractWrappersError.SubscriptionAlreadyPresent); } this._blockAndLogStreamerIfExists = new BlockAndLogStreamer( - this._getBlockOrNullAsync.bind(this), - this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper), + this._blockstreamGetBlockOrNullAsync.bind(this), + this._blockstreamGetLogsAsync.bind(this), ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose), ); const catchAllLogFilter = {}; @@ -196,12 +197,30 @@ export abstract class ContractWrapper { ); } // This method only exists in order to comply with the expected interface of Blockstream's constructor - private async _getBlockOrNullAsync(): Promise<BlockWithoutTransactionData | null> { - const blockIfExists = await this._web3Wrapper.getBlockIfExistsAsync.bind(this._web3Wrapper); - if (_.isUndefined(blockIfExists)) { - return null; - } - return blockIfExists; + private async _blockstreamGetBlockOrNullAsync(hash: string): Promise<Block | null> { + const shouldIncludeTransactionData = false; + const blockOrNull = await this._web3Wrapper.sendRawPayloadAsync<Block | null>({ + method: 'eth_getBlockByHash', + params: [hash, shouldIncludeTransactionData], + }); + return blockOrNull; + } + // This method only exists in order to comply with the expected interface of Blockstream's constructor + private async _blockstreamGetLatestBlockOrNullAsync(): Promise<Block | null> { + const shouldIncludeTransactionData = false; + const blockOrNull = await this._web3Wrapper.sendRawPayloadAsync<Block | null>({ + method: 'eth_getBlockByNumber', + params: [BlockParamLiteral.Latest, shouldIncludeTransactionData], + }); + return blockOrNull; + } + // This method only exists in order to comply with the expected interface of Blockstream's constructor + private async _blockstreamGetLogsAsync(filterOptions: FilterObject): Promise<RawLogEntry[]> { + const logs = await this._web3Wrapper.sendRawPayloadAsync<RawLogEntry[]>({ + method: 'eth_getLogs', + params: [filterOptions], + }); + return logs as RawLogEntry[]; } // HACK: This should be a package-scoped method (which doesn't exist in TS) // We don't want this method available in the public interface for all classes @@ -221,14 +240,14 @@ export abstract class ContractWrapper { delete this._blockAndLogStreamerIfExists; } private async _reconcileBlockAsync(): Promise<void> { - const latestBlockIfExists = await this._web3Wrapper.getBlockIfExistsAsync(BlockParamLiteral.Latest); - if (_.isUndefined(latestBlockIfExists)) { + const latestBlockOrNull = await this._blockstreamGetLatestBlockOrNullAsync(); + if (_.isNull(latestBlockOrNull)) { return; // noop } // We need to coerce to Block type cause Web3.Block includes types for mempool blocks if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined - await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlockIfExists as any) as Block); + await this._blockAndLogStreamerIfExists.reconcileNewBlock(latestBlockOrNull); } } } diff --git a/packages/ethereum-types/src/index.ts b/packages/ethereum-types/src/index.ts index 8f8f4b7e6..a3ff2fddb 100644 --- a/packages/ethereum-types/src/index.ts +++ b/packages/ethereum-types/src/index.ts @@ -181,6 +181,7 @@ export interface CallData extends CallTxDataBase { export interface FilterObject { fromBlock?: number | string; toBlock?: number | string; + blockHash?: string; address?: string; topics?: LogTopic[]; } diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json index d4b0e6607..9ab0905fe 100644 --- a/packages/order-watcher/CHANGELOG.json +++ b/packages/order-watcher/CHANGELOG.json @@ -1,21 +1,36 @@ [ { - "timestamp": 1537875740, + "version": "2.0.0", + "changes": [ + { + "note": + "Fixes dropped events issue by fetching logs by blockHash instead of blockNumber. Support for fetching by blockHash was added in Geth > v1.8.13 and Parity > v2.1.0. Infura works too.", + "pr": 1080 + }, + { + "note": + "Fix misunderstanding about blockstream interface callbacks and pass the raw JSON RPC responses to it", + "pr": 1080 + } + ] + }, + { "version": "1.0.5", "changes": [ { "note": "Dependencies updated" } - ] + ], + "timestamp": 1537875740 }, { - "timestamp": 1537541580, "version": "1.0.4", "changes": [ { "note": "Dependencies updated" } - ] + ], + "timestamp": 1537541580 }, { "version": "1.0.3", diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index d383211a8..b00a76e55 100644 --- a/packages/order-watcher/package.json +++ b/packages/order-watcher/package.json @@ -82,7 +82,7 @@ "@0xproject/web3-wrapper": "^3.0.0", "bintrees": "^1.0.2", "ethereum-types": "^1.0.7", - "ethereumjs-blockstream": "5.0.0", + "ethereumjs-blockstream": "6.0.0", "ethers": "3.0.22", "lodash": "^4.17.5" }, diff --git a/packages/order-watcher/src/order_watcher/event_watcher.ts b/packages/order-watcher/src/order_watcher/event_watcher.ts index eca235e26..9ea301815 100644 --- a/packages/order-watcher/src/order_watcher/event_watcher.ts +++ b/packages/order-watcher/src/order_watcher/event_watcher.ts @@ -1,6 +1,6 @@ import { intervalUtils, logUtils } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; -import { BlockParamLiteral, BlockWithoutTransactionData, LogEntry, Provider } from 'ethereum-types'; +import { marshaller, Web3Wrapper } from '@0xproject/web3-wrapper'; +import { BlockParamLiteral, FilterObject, LogEntry, Provider, RawLogEntry } from 'ethereum-types'; import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream'; import * as _ from 'lodash'; @@ -20,7 +20,6 @@ enum LogEventState { */ export class EventWatcher { private readonly _web3Wrapper: Web3Wrapper; - private readonly _stateLayer: BlockParamLiteral; private readonly _isVerbose: boolean; private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined; private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer; @@ -35,7 +34,6 @@ export class EventWatcher { ) { this._isVerbose = isVerbose; this._web3Wrapper = new Web3Wrapper(provider); - this._stateLayer = stateLayer; this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs) ? DEFAULT_EVENT_POLLING_INTERVAL_MS : pollingIntervalIfExistsMs; @@ -62,8 +60,8 @@ export class EventWatcher { throw new Error(OrderWatcherError.SubscriptionAlreadyPresent); } this._blockAndLogStreamerIfExists = new BlockAndLogStreamer( - this._getBlockOrNullAsync.bind(this), - this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper), + this._blockstreamGetBlockOrNullAsync.bind(this), + this._blockstreamGetLogsAsync.bind(this), this._onBlockAndLogStreamerError.bind(this), ); const catchAllLogFilter = {}; @@ -83,12 +81,30 @@ export class EventWatcher { ); } // This method only exists in order to comply with the expected interface of Blockstream's constructor - private async _getBlockOrNullAsync(): Promise<BlockWithoutTransactionData | null> { - const blockIfExists = await this._web3Wrapper.getBlockIfExistsAsync.bind(this._web3Wrapper); - if (_.isUndefined(blockIfExists)) { - return null; - } - return blockIfExists; + private async _blockstreamGetBlockOrNullAsync(hash: string): Promise<Block | null> { + const shouldIncludeTransactionData = false; + const blockOrNull = await this._web3Wrapper.sendRawPayloadAsync<Block | null>({ + method: 'eth_getBlockByHash', + params: [hash, shouldIncludeTransactionData], + }); + return blockOrNull; + } + // This method only exists in order to comply with the expected interface of Blockstream's constructor + private async _blockstreamGetLatestBlockOrNullAsync(): Promise<Block | null> { + const shouldIncludeTransactionData = false; + const blockOrNull = await this._web3Wrapper.sendRawPayloadAsync<Block | null>({ + method: 'eth_getBlockByNumber', + params: [BlockParamLiteral.Latest, shouldIncludeTransactionData], + }); + return blockOrNull; + } + // This method only exists in order to comply with the expected interface of Blockstream's constructor + private async _blockstreamGetLogsAsync(filterOptions: FilterObject): Promise<RawLogEntry[]> { + const logs = await this._web3Wrapper.sendRawPayloadAsync<RawLogEntry[]>({ + method: 'eth_getLogs', + params: [filterOptions], + }); + return logs as RawLogEntry[]; } private _stopBlockAndLogStream(): void { if (_.isUndefined(this._blockAndLogStreamerIfExists)) { @@ -103,19 +119,20 @@ export class EventWatcher { private async _onLogStateChangedAsync( callback: EventWatcherCallback, isRemoved: boolean, - log: LogEntry, + rawLog: RawLogEntry, ): Promise<void> { + const log: LogEntry = marshaller.unmarshalLog(rawLog); await this._emitDifferencesAsync(log, isRemoved ? LogEventState.Removed : LogEventState.Added, callback); } private async _reconcileBlockAsync(): Promise<void> { - const latestBlockIfExists = await this._web3Wrapper.getBlockIfExistsAsync(this._stateLayer); - if (_.isUndefined(latestBlockIfExists)) { + const latestBlockOrNull = await this._blockstreamGetLatestBlockOrNullAsync(); + if (_.isNull(latestBlockOrNull)) { return; // noop } // We need to coerce to Block type cause Web3.Block includes types for mempool blocks if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined - await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlockIfExists as any) as Block); + await this._blockAndLogStreamerIfExists.reconcileNewBlock(latestBlockOrNull); } } private async _emitDifferencesAsync( diff --git a/packages/web3-wrapper/CHANGELOG.json b/packages/web3-wrapper/CHANGELOG.json index b1ea2fe2e..8895951bc 100644 --- a/packages/web3-wrapper/CHANGELOG.json +++ b/packages/web3-wrapper/CHANGELOG.json @@ -6,6 +6,11 @@ "note": "Rename `getBlockAsync` to `getBlockIfExistsAsync` and rather then throw if the requested block wasn't found, return undefined.", "pr": 1082 + }, + { + "note": + "Expose `sendRawPayloadAsync` so one can easily extend `Web3Wrapper` with their own custom JSON RPC calls", + "pr": 1080 } ], "timestamp": 1537875740 diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts index dc634a57f..d52c1cb6e 100644 --- a/packages/web3-wrapper/src/web3_wrapper.ts +++ b/packages/web3-wrapper/src/web3_wrapper.ts @@ -193,7 +193,7 @@ export class Web3Wrapper { * @returns Ethereum node's version string */ public async getNodeVersionAsync(): Promise<string> { - const nodeVersion = await this._sendRawPayloadAsync<string>({ method: 'web3_clientVersion' }); + const nodeVersion = await this.sendRawPayloadAsync<string>({ method: 'web3_clientVersion' }); return nodeVersion; } /** @@ -201,7 +201,7 @@ export class Web3Wrapper { * @returns The network id */ public async getNetworkIdAsync(): Promise<number> { - const networkIdStr = await this._sendRawPayloadAsync<string>({ method: 'net_version' }); + const networkIdStr = await this.sendRawPayloadAsync<string>({ method: 'net_version' }); const networkId = _.parseInt(networkIdStr); return networkId; } @@ -212,7 +212,7 @@ export class Web3Wrapper { */ public async getTransactionReceiptAsync(txHash: string): Promise<TransactionReceipt> { assert.isHexString('txHash', txHash); - const transactionReceipt = await this._sendRawPayloadAsync<TransactionReceipt>({ + const transactionReceipt = await this.sendRawPayloadAsync<TransactionReceipt>({ method: 'eth_getTransactionReceipt', params: [txHash], }); @@ -228,7 +228,7 @@ export class Web3Wrapper { */ public async getTransactionByHashAsync(txHash: string): Promise<Transaction> { assert.isHexString('txHash', txHash); - const transaction = await this._sendRawPayloadAsync<Transaction>({ + const transaction = await this.sendRawPayloadAsync<Transaction>({ method: 'eth_getTransactionByHash', params: [txHash], }); @@ -247,7 +247,7 @@ export class Web3Wrapper { } const marshalledDefaultBlock = marshaller.marshalBlockParam(defaultBlock); const encodedOwner = marshaller.marshalAddress(owner); - const balanceInWei = await this._sendRawPayloadAsync<string>({ + const balanceInWei = await this.sendRawPayloadAsync<string>({ method: 'eth_getBalance', params: [encodedOwner, marshalledDefaultBlock], }); @@ -279,7 +279,7 @@ export class Web3Wrapper { } const marshalledDefaultBlock = marshaller.marshalBlockParam(defaultBlock); const encodedAddress = marshaller.marshalAddress(address); - const code = await this._sendRawPayloadAsync<string>({ + const code = await this.sendRawPayloadAsync<string>({ method: 'eth_getCode', params: [encodedAddress, marshalledDefaultBlock], }); @@ -293,7 +293,7 @@ export class Web3Wrapper { */ public async getTransactionTraceAsync(txHash: string, traceParams: TraceParams): Promise<TransactionTrace> { assert.isHexString('txHash', txHash); - const trace = await this._sendRawPayloadAsync<TransactionTrace>({ + const trace = await this.sendRawPayloadAsync<TransactionTrace>({ method: 'debug_traceTransaction', params: [txHash, traceParams], }); @@ -308,7 +308,7 @@ export class Web3Wrapper { public async signMessageAsync(address: string, message: string): Promise<string> { assert.isETHAddressHex('address', address); assert.isString('message', message); // TODO: Should this be stricter? Hex string? - const signData = await this._sendRawPayloadAsync<string>({ + const signData = await this.sendRawPayloadAsync<string>({ method: 'eth_sign', params: [address, message], }); @@ -319,7 +319,7 @@ export class Web3Wrapper { * @returns Block number */ public async getBlockNumberAsync(): Promise<number> { - const blockNumberHex = await this._sendRawPayloadAsync<string>({ + const blockNumberHex = await this.sendRawPayloadAsync<string>({ method: 'eth_blockNumber', params: [], }); @@ -339,7 +339,7 @@ export class Web3Wrapper { const encodedBlockParam = marshaller.marshalBlockParam(blockParam); const method = utils.isHexStrict(blockParam) ? 'eth_getBlockByHash' : 'eth_getBlockByNumber'; const shouldIncludeTransactionData = false; - const blockWithoutTransactionDataWithHexValuesOrNull = await this._sendRawPayloadAsync< + const blockWithoutTransactionDataWithHexValuesOrNull = await this.sendRawPayloadAsync< BlockWithoutTransactionDataRPC >({ method, @@ -366,7 +366,7 @@ export class Web3Wrapper { } const method = utils.isHexStrict(blockParam) ? 'eth_getBlockByHash' : 'eth_getBlockByNumber'; const shouldIncludeTransactionData = true; - const blockWithTransactionDataWithHexValues = await this._sendRawPayloadAsync<BlockWithTransactionDataRPC>({ + const blockWithTransactionDataWithHexValues = await this.sendRawPayloadAsync<BlockWithTransactionDataRPC>({ method, params: [encodedBlockParam, shouldIncludeTransactionData], }); @@ -393,7 +393,7 @@ export class Web3Wrapper { * @returns Available user addresses */ public async getAvailableAddressesAsync(): Promise<string[]> { - const addresses = await this._sendRawPayloadAsync<string>({ + const addresses = await this.sendRawPayloadAsync<string>({ method: 'eth_accounts', params: [], }); @@ -405,7 +405,7 @@ export class Web3Wrapper { * @returns The snapshot id. This can be used to revert to this snapshot */ public async takeSnapshotAsync(): Promise<number> { - const snapshotId = Number(await this._sendRawPayloadAsync<string>({ method: 'evm_snapshot', params: [] })); + const snapshotId = Number(await this.sendRawPayloadAsync<string>({ method: 'evm_snapshot', params: [] })); return snapshotId; } /** @@ -415,14 +415,14 @@ export class Web3Wrapper { */ public async revertSnapshotAsync(snapshotId: number): Promise<boolean> { assert.isNumber('snapshotId', snapshotId); - const didRevert = await this._sendRawPayloadAsync<boolean>({ method: 'evm_revert', params: [snapshotId] }); + const didRevert = await this.sendRawPayloadAsync<boolean>({ method: 'evm_revert', params: [snapshotId] }); return didRevert; } /** * Mine a block on a TestRPC/Ganache local node */ public async mineBlockAsync(): Promise<void> { - await this._sendRawPayloadAsync<string>({ method: 'evm_mine', params: [] }); + await this.sendRawPayloadAsync<string>({ method: 'evm_mine', params: [] }); } /** * Increase the next blocks timestamp on TestRPC/Ganache or Geth local node. @@ -434,9 +434,9 @@ export class Web3Wrapper { // Detect Geth vs. Ganache and use appropriate endpoint. const version = await this.getNodeVersionAsync(); if (_.includes(version, uniqueVersionIds.geth)) { - return this._sendRawPayloadAsync<number>({ method: 'debug_increaseTime', params: [timeDelta] }); + return this.sendRawPayloadAsync<number>({ method: 'debug_increaseTime', params: [timeDelta] }); } else if (_.includes(version, uniqueVersionIds.ganache)) { - return this._sendRawPayloadAsync<number>({ method: 'evm_increaseTime', params: [timeDelta] }); + return this.sendRawPayloadAsync<number>({ method: 'evm_increaseTime', params: [timeDelta] }); } else { throw new Error(`Unknown client version: ${version}`); } @@ -447,6 +447,12 @@ export class Web3Wrapper { * @returns The corresponding log entries */ public async getLogsAsync(filter: FilterObject): Promise<LogEntry[]> { + if (!_.isUndefined(filter.blockHash) && (!_.isUndefined(filter.fromBlock) || !_.isUndefined(filter.toBlock))) { + throw new Error( + `Cannot specify 'blockHash' as well as 'fromBlock'/'toBlock' in the filter supplied to 'getLogsAsync'`, + ); + } + let fromBlock = filter.fromBlock; if (_.isNumber(fromBlock)) { fromBlock = utils.numberToHex(fromBlock); @@ -464,7 +470,7 @@ export class Web3Wrapper { method: 'eth_getLogs', params: [serializedFilter], }; - const rawLogs = await this._sendRawPayloadAsync<RawLogEntry[]>(payload); + const rawLogs = await this.sendRawPayloadAsync<RawLogEntry[]>(payload); const formattedLogs = _.map(rawLogs, marshaller.unmarshalLog.bind(marshaller)); return formattedLogs; } @@ -480,7 +486,7 @@ export class Web3Wrapper { schemas.jsNumber, ]); const txDataHex = marshaller.marshalTxData(txData); - const gasHex = await this._sendRawPayloadAsync<string>({ method: 'eth_estimateGas', params: [txDataHex] }); + const gasHex = await this.sendRawPayloadAsync<string>({ method: 'eth_estimateGas', params: [txDataHex] }); const gas = utils.convertHexToNumber(gasHex); return gas; } @@ -501,7 +507,7 @@ export class Web3Wrapper { } const marshalledDefaultBlock = marshaller.marshalBlockParam(defaultBlock); const callDataHex = marshaller.marshalCallData(callData); - const rawCallResult = await this._sendRawPayloadAsync<string>({ + const rawCallResult = await this.sendRawPayloadAsync<string>({ method: 'eth_call', params: [callDataHex, marshalledDefaultBlock], }); @@ -522,7 +528,7 @@ export class Web3Wrapper { schemas.jsNumber, ]); const txDataHex = marshaller.marshalTxData(txData); - const txHash = await this._sendRawPayloadAsync<string>({ method: 'eth_sendTransaction', params: [txDataHex] }); + const txHash = await this.sendRawPayloadAsync<string>({ method: 'eth_sendTransaction', params: [txDataHex] }); return txHash; } /** @@ -632,7 +638,24 @@ export class Web3Wrapper { */ public async setHeadAsync(blockNumber: number): Promise<void> { assert.isNumber('blockNumber', blockNumber); - await this._sendRawPayloadAsync<void>({ method: 'debug_setHead', params: [utils.numberToHex(blockNumber)] }); + await this.sendRawPayloadAsync<void>({ method: 'debug_setHead', params: [utils.numberToHex(blockNumber)] }); + } + /** + * Sends a raw Ethereum JSON RPC payload and returns the response's `result` key + * @param payload A partial JSON RPC payload. No need to include version, id, params (if none needed) + * @return The contents nested under the result key of the response body + */ + public async sendRawPayloadAsync<A>(payload: Partial<JSONRPCRequestPayload>): Promise<A> { + const sendAsync = this._provider.sendAsync.bind(this._provider); + const payloadWithDefaults = { + id: this._jsonRpcRequestId++, + params: [], + jsonrpc: '2.0', + ...payload, + }; + const response = await promisify<JSONRPCResponsePayload>(sendAsync)(payloadWithDefaults); + const result = response.result; + return result; } /** * Returns either NodeType.Geth or NodeType.Ganache depending on the type of @@ -648,16 +671,4 @@ export class Web3Wrapper { throw new Error(`Unknown client version: ${version}`); } } - private async _sendRawPayloadAsync<A>(payload: Partial<JSONRPCRequestPayload>): Promise<A> { - const sendAsync = this._provider.sendAsync.bind(this._provider); - const payloadWithDefaults = { - id: this._jsonRpcRequestId++, - params: [], - jsonrpc: '2.0', - ...payload, - }; - const response = await promisify<JSONRPCResponsePayload>(sendAsync)(payloadWithDefaults); - const result = response.result; - return result; - } } // tslint:disable-line:max-file-line-count |