aboutsummaryrefslogtreecommitdiffstats
path: root/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/0x.js/src/contract_wrappers/contract_wrapper.ts')
-rw-r--r--packages/0x.js/src/contract_wrappers/contract_wrapper.ts121
1 files changed, 69 insertions, 52 deletions
diff --git a/packages/0x.js/src/contract_wrappers/contract_wrapper.ts b/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
index d56b8632d..27551c01d 100644
--- a/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
+++ b/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
@@ -1,11 +1,13 @@
-import {Web3Wrapper} from '@0xproject/web3-wrapper';
-import {Block, BlockAndLogStreamer} from 'ethereumjs-blockstream';
+import { intervalUtils } from '@0xproject/utils';
+import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream';
import * as _ from 'lodash';
import * as Web3 from 'web3';
import {
Artifact,
BlockParamLiteral,
+ BlockRange,
ContractEventArgs,
ContractEvents,
EventCallback,
@@ -13,15 +15,15 @@ import {
InternalZeroExError,
LogWithDecodedArgs,
RawLog,
- SubscriptionOpts,
ZeroExError,
} from '../types';
-import {AbiDecoder} from '../utils/abi_decoder';
-import {constants} from '../utils/constants';
-import {filterUtils} from '../utils/filter_utils';
-import {intervalUtils} from '../utils/interval_utils';
+import { AbiDecoder } from '../utils/abi_decoder';
+import { constants } from '../utils/constants';
+import { filterUtils } from '../utils/filter_utils';
-const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {[contractName: string]: ZeroExError} = {
+const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {
+ [contractName: string]: ZeroExError;
+} = {
ZRX: ZeroExError.ZRXContractDoesNotExist,
EtherToken: ZeroExError.EtherTokenContractDoesNotExist,
Token: ZeroExError.TokenContractDoesNotExist,
@@ -34,26 +36,25 @@ export class ContractWrapper {
protected _web3Wrapper: Web3Wrapper;
private _networkId: number;
private _abiDecoder?: AbiDecoder;
- private _blockAndLogStreamer: BlockAndLogStreamer|undefined;
+ private _blockAndLogStreamerIfExists: BlockAndLogStreamer | undefined;
private _blockAndLogStreamInterval: NodeJS.Timer;
- private _filters: {[filterToken: string]: Web3.FilterObject};
- private _filterCallbacks: {[filterToken: string]: EventCallback<ContractEventArgs>};
- private _onLogAddedSubscriptionToken: string|undefined;
- private _onLogRemovedSubscriptionToken: string|undefined;
+ private _filters: { [filterToken: string]: Web3.FilterObject };
+ private _filterCallbacks: {
+ [filterToken: string]: EventCallback<ContractEventArgs>;
+ };
+ private _onLogAddedSubscriptionToken: string | undefined;
+ private _onLogRemovedSubscriptionToken: string | undefined;
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder?: AbiDecoder) {
this._web3Wrapper = web3Wrapper;
this._networkId = networkId;
this._abiDecoder = abiDecoder;
this._filters = {};
this._filterCallbacks = {};
- this._blockAndLogStreamer = undefined;
+ this._blockAndLogStreamerIfExists = undefined;
this._onLogAddedSubscriptionToken = undefined;
this._onLogRemovedSubscriptionToken = undefined;
}
- /**
- * Cancels all existing subscriptions
- */
- public unsubscribeAll(): void {
+ protected unsubscribeAll(): void {
const filterTokens = _.keys(this._filterCallbacks);
_.each(filterTokens, filterToken => {
this._unsubscribe(filterToken);
@@ -74,27 +75,36 @@ export class ContractWrapper {
}
}
protected _subscribe<ArgsType extends ContractEventArgs>(
- address: string, eventName: ContractEvents, indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi,
- callback: EventCallback<ArgsType>): string {
+ address: string,
+ eventName: ContractEvents,
+ indexFilterValues: IndexedFilterValues,
+ abi: Web3.ContractAbi,
+ callback: EventCallback<ArgsType>,
+ ): string {
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi);
- if (_.isUndefined(this._blockAndLogStreamer)) {
+ if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
this._startBlockAndLogStream();
}
const filterToken = filterUtils.generateUUID();
this._filters[filterToken] = filter;
- this._filterCallbacks[filterToken] = callback;
+ this._filterCallbacks[filterToken] = callback as EventCallback<ContractEventArgs>;
return filterToken;
}
protected async _getLogsAsync<ArgsType extends ContractEventArgs>(
- address: string, eventName: ContractEvents, subscriptionOpts: SubscriptionOpts,
- indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
- const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, subscriptionOpts);
+ address: string,
+ eventName: ContractEvents,
+ blockRange: BlockRange,
+ indexFilterValues: IndexedFilterValues,
+ abi: Web3.ContractAbi,
+ ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
+ const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange);
const logs = await this._web3Wrapper.getLogsAsync(filter);
const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
return logsWithDecodedArguments;
}
protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
- log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog {
+ log: Web3.LogEntry,
+ ): LogWithDecodedArgs<ArgsType> | RawLog {
if (_.isUndefined(this._abiDecoder)) {
throw new Error(InternalZeroExError.NoAbiDecoder);
}
@@ -102,7 +112,8 @@ export class ContractWrapper {
return logWithDecodedArgs;
}
protected async _instantiateContractIfExistsAsync(
- artifact: Artifact, addressIfExists?: string,
+ artifact: Artifact,
+ addressIfExists?: string,
): Promise<Web3.ContractInstance> {
let contractAddress: string;
if (_.isUndefined(addressIfExists)) {
@@ -117,9 +128,7 @@ export class ContractWrapper {
if (!doesContractExist) {
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
}
- const contractInstance = this._web3Wrapper.getContractInstance(
- artifact.abi, contractAddress,
- );
+ const contractInstance = this._web3Wrapper.getContractInstance(artifact.abi, contractAddress);
return contractInstance;
}
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
@@ -146,45 +155,53 @@ export class ContractWrapper {
});
}
private _startBlockAndLogStream(): void {
- this._blockAndLogStreamer = new BlockAndLogStreamer(
+ if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
+ throw new Error(ZeroExError.SubscriptionAlreadyPresent);
+ }
+ this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
);
const catchAllLogFilter = {};
- this._blockAndLogStreamer.addLogFilter(catchAllLogFilter);
+ this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
this._blockAndLogStreamInterval = intervalUtils.setAsyncExcludingInterval(
- this._reconcileBlockAsync.bind(this), constants.DEFAULT_BLOCK_POLLING_INTERVAL,
+ this._reconcileBlockAsync.bind(this),
+ constants.DEFAULT_BLOCK_POLLING_INTERVAL,
+ this._onReconcileBlockError.bind(this),
);
let isRemoved = false;
- this._onLogAddedSubscriptionToken = this._blockAndLogStreamer.subscribeToOnLogAdded(
+ this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
this._onLogStateChanged.bind(this, isRemoved),
);
isRemoved = true;
- this._onLogRemovedSubscriptionToken = this._blockAndLogStreamer.subscribeToOnLogRemoved(
+ this._onLogRemovedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogRemoved(
this._onLogStateChanged.bind(this, isRemoved),
);
}
+ private _onReconcileBlockError(err: Error): void {
+ const filterTokens = _.keys(this._filterCallbacks);
+ _.each(filterTokens, filterToken => {
+ this._unsubscribe(filterToken, err);
+ });
+ }
+ private _setNetworkId(networkId: number): void {
+ this._networkId = networkId;
+ }
private _stopBlockAndLogStream(): void {
- (this._blockAndLogStreamer as BlockAndLogStreamer).unsubscribeFromOnLogAdded(
- this._onLogAddedSubscriptionToken as string);
- (this._blockAndLogStreamer as BlockAndLogStreamer).unsubscribeFromOnLogRemoved(
- this._onLogRemovedSubscriptionToken as string);
+ if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
+ throw new Error(ZeroExError.SubscriptionNotFound);
+ }
+ this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string);
+ this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string);
intervalUtils.clearAsyncExcludingInterval(this._blockAndLogStreamInterval);
- delete this._blockAndLogStreamer;
+ delete this._blockAndLogStreamerIfExists;
}
private async _reconcileBlockAsync(): Promise<void> {
- try {
- const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
- // We need to coerce to Block type cause Web3.Block includes types for mempool blocks
- if (!_.isUndefined(this._blockAndLogStreamer)) {
- // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
- await this._blockAndLogStreamer.reconcileNewBlock(latestBlock as any as Block);
- }
- } catch (err) {
- const filterTokens = _.keys(this._filterCallbacks);
- _.each(filterTokens, filterToken => {
- this._unsubscribe(filterToken, err);
- });
+ const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
+ // 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((latestBlock as any) as Block);
}
}
}