Merge pull request #1080 from 0xProject/upgradeBlockstream
Fix dropped events issue in Order-watcher and Contract-wrappers subscriptions
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,6 +181,7 @@ export interface CallData extends CallTxDataBase {
|
||||
export interface FilterObject {
|
||||
fromBlock?: number | string;
|
||||
toBlock?: number | string;
|
||||
blockHash?: string;
|
||||
address?: string;
|
||||
topics?: LogTopic[];
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@@ -5203,6 +5203,14 @@ ethereumjs-blockstream@5.0.0:
|
||||
source-map-support "0.5.6"
|
||||
uuid "3.2.1"
|
||||
|
||||
ethereumjs-blockstream@6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ethereumjs-blockstream/-/ethereumjs-blockstream-6.0.0.tgz#79d726d1f358935eb65195e91d40344c31e87eff"
|
||||
dependencies:
|
||||
immutable "3.8.2"
|
||||
source-map-support "0.5.6"
|
||||
uuid "3.2.1"
|
||||
|
||||
ethereumjs-tx@0xProject/ethereumjs-tx#fake-tx-include-signature-by-default:
|
||||
version "1.3.4"
|
||||
resolved "https://codeload.github.com/0xProject/ethereumjs-tx/tar.gz/29d1153889c389591f74b2401da8a0c6ad40f9a7"
|
||||
@@ -6053,7 +6061,7 @@ ganache-core@0xProject/ganache-core#monorepo-dep:
|
||||
ethereumjs-tx "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default"
|
||||
ethereumjs-util "^5.2.0"
|
||||
ethereumjs-vm "2.3.5"
|
||||
ethereumjs-wallet "~0.6.0"
|
||||
ethereumjs-wallet "0.6.0"
|
||||
fake-merkle-patricia-tree "~1.0.1"
|
||||
heap "~0.2.6"
|
||||
js-scrypt "^0.2.0"
|
||||
|
||||
Reference in New Issue
Block a user