aboutsummaryrefslogtreecommitdiffstats
path: root/packages/0x.js/src
diff options
context:
space:
mode:
authorJacob Evans <dekz@dekz.net>2017-11-23 11:37:34 +0800
committerGitHub <noreply@github.com>2017-11-23 11:37:34 +0800
commit437ac301db3c03c0abd0f741a17c56a4eebc2aa4 (patch)
tree2bd3276289578e99140f8f1168af58f07d566476 /packages/0x.js/src
parent9c9ce9752537122df51b935bf1f63f128414fc0f (diff)
parent215740fab27d75630f55e7a3194b9e498b511c08 (diff)
downloaddexon-sol-tools-437ac301db3c03c0abd0f741a17c56a4eebc2aa4.tar
dexon-sol-tools-437ac301db3c03c0abd0f741a17c56a4eebc2aa4.tar.gz
dexon-sol-tools-437ac301db3c03c0abd0f741a17c56a4eebc2aa4.tar.bz2
dexon-sol-tools-437ac301db3c03c0abd0f741a17c56a4eebc2aa4.tar.lz
dexon-sol-tools-437ac301db3c03c0abd0f741a17c56a4eebc2aa4.tar.xz
dexon-sol-tools-437ac301db3c03c0abd0f741a17c56a4eebc2aa4.tar.zst
dexon-sol-tools-437ac301db3c03c0abd0f741a17c56a4eebc2aa4.zip
Merge branch 'development' into feature/calculate-remaining-proportions
Diffstat (limited to 'packages/0x.js/src')
-rw-r--r--packages/0x.js/src/index.ts2
-rw-r--r--packages/0x.js/src/order_watcher/event_watcher.ts12
-rw-r--r--packages/0x.js/src/order_watcher/expiration_watcher.ts76
-rw-r--r--packages/0x.js/src/order_watcher/order_state_watcher.ts76
-rw-r--r--packages/0x.js/src/types.ts20
-rw-r--r--packages/0x.js/src/utils/order_validation_utils.ts4
-rw-r--r--packages/0x.js/src/utils/utils.ts7
-rw-r--r--packages/0x.js/src/web3_wrapper.ts38
8 files changed, 189 insertions, 46 deletions
diff --git a/packages/0x.js/src/index.ts b/packages/0x.js/src/index.ts
index 1b3e893ba..e529e2858 100644
--- a/packages/0x.js/src/index.ts
+++ b/packages/0x.js/src/index.ts
@@ -6,8 +6,6 @@ export {
ECSignature,
ZeroExError,
EventCallback,
- EventCallbackAsync,
- EventCallbackSync,
ExchangeContractErrs,
ContractEvent,
Token,
diff --git a/packages/0x.js/src/order_watcher/event_watcher.ts b/packages/0x.js/src/order_watcher/event_watcher.ts
index 81529a98c..ecbab0cd5 100644
--- a/packages/0x.js/src/order_watcher/event_watcher.ts
+++ b/packages/0x.js/src/order_watcher/event_watcher.ts
@@ -12,7 +12,7 @@ import {intervalUtils} from '../utils/interval_utils';
import {assert} from '../utils/assert';
import {utils} from '../utils/utils';
-const DEFAULT_EVENT_POLLING_INTERVAL = 200;
+const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200;
enum LogEventState {
Removed,
@@ -28,11 +28,11 @@ export class EventWatcher {
private _pollingIntervalMs: number;
private _intervalIdIfExists?: NodeJS.Timer;
private _lastEvents: Web3.LogEntry[] = [];
- constructor(web3Wrapper: Web3Wrapper, pollingIntervalMs: undefined|number) {
+ constructor(web3Wrapper: Web3Wrapper, pollingIntervalIfExistsMs: undefined|number) {
this._web3Wrapper = web3Wrapper;
- this._pollingIntervalMs = _.isUndefined(pollingIntervalMs) ?
- DEFAULT_EVENT_POLLING_INTERVAL :
- pollingIntervalMs;
+ this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs) ?
+ DEFAULT_EVENT_POLLING_INTERVAL_MS :
+ pollingIntervalIfExistsMs;
}
public subscribe(callback: EventWatcherCallback): void {
assert.isFunction('callback', callback);
@@ -81,7 +81,7 @@ export class EventWatcher {
...log,
};
if (!_.isUndefined(this._intervalIdIfExists)) {
- await callback(logEvent);
+ callback(logEvent);
}
}
}
diff --git a/packages/0x.js/src/order_watcher/expiration_watcher.ts b/packages/0x.js/src/order_watcher/expiration_watcher.ts
new file mode 100644
index 000000000..717edaad7
--- /dev/null
+++ b/packages/0x.js/src/order_watcher/expiration_watcher.ts
@@ -0,0 +1,76 @@
+import * as _ from 'lodash';
+import {BigNumber} from 'bignumber.js';
+import {RBTree} from 'bintrees';
+import {utils} from '../utils/utils';
+import {intervalUtils} from '../utils/interval_utils';
+import {SignedOrder, ZeroExError} from '../types';
+import {ZeroEx} from '../0x';
+
+const DEFAULT_EXPIRATION_MARGIN_MS = 0;
+const DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS = 50;
+
+/**
+ * This class includes the functionality to detect expired orders.
+ * It stores them in a min heap by expiration time and checks for expired ones every `orderExpirationCheckingIntervalMs`
+ */
+export class ExpirationWatcher {
+ private orderHashByExpirationRBTree: RBTree<string>;
+ private expiration: {[orderHash: string]: BigNumber} = {};
+ private orderExpirationCheckingIntervalMs: number;
+ private expirationMarginMs: number;
+ private orderExpirationCheckingIntervalIdIfExists?: NodeJS.Timer;
+ constructor(expirationMarginIfExistsMs?: number,
+ orderExpirationCheckingIntervalIfExistsMs?: number) {
+ this.expirationMarginMs = expirationMarginIfExistsMs ||
+ DEFAULT_EXPIRATION_MARGIN_MS;
+ this.orderExpirationCheckingIntervalMs = expirationMarginIfExistsMs ||
+ DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS;
+ const scoreFunction = (orderHash: string) => this.expiration[orderHash].toNumber();
+ const comparator = (lhs: string, rhs: string) => scoreFunction(lhs) - scoreFunction(rhs);
+ this.orderHashByExpirationRBTree = new RBTree(comparator);
+ }
+ public subscribe(callbackAsync: (orderHash: string) => Promise<void>): void {
+ if (!_.isUndefined(this.orderExpirationCheckingIntervalIdIfExists)) {
+ throw new Error(ZeroExError.SubscriptionAlreadyPresent);
+ }
+ this.orderExpirationCheckingIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
+ this.pruneExpiredOrdersAsync.bind(this, callbackAsync), this.orderExpirationCheckingIntervalMs,
+ );
+ }
+ public unsubscribe(): void {
+ if (_.isUndefined(this.orderExpirationCheckingIntervalIdIfExists)) {
+ throw new Error(ZeroExError.SubscriptionNotFound);
+ }
+ intervalUtils.clearAsyncExcludingInterval(this.orderExpirationCheckingIntervalIdIfExists);
+ delete this.orderExpirationCheckingIntervalIdIfExists;
+ }
+ public addOrder(orderHash: string, expirationUnixTimestampMs: BigNumber): void {
+ this.expiration[orderHash] = expirationUnixTimestampMs;
+ this.orderHashByExpirationRBTree.insert(orderHash);
+ }
+ public removeOrder(orderHash: string): void {
+ this.orderHashByExpirationRBTree.remove(orderHash);
+ delete this.expiration[orderHash];
+ }
+ private async pruneExpiredOrdersAsync(callbackAsync: (orderHash: string) => Promise<void>): Promise<void> {
+ const currentUnixTimestampMs = utils.getCurrentUnixTimestampMs();
+ while (true) {
+ const hasTrakedOrders = this.orderHashByExpirationRBTree.size === 0;
+ if (hasTrakedOrders) {
+ break;
+ }
+ const nextOrderHashToExpire = this.orderHashByExpirationRBTree.min();
+ const hasNoExpiredOrders = this.expiration[nextOrderHashToExpire].greaterThan(
+ currentUnixTimestampMs.plus(this.expirationMarginMs),
+ );
+ const isSubscriptionActive = _.isUndefined(this.orderExpirationCheckingIntervalIdIfExists);
+ if (hasNoExpiredOrders || isSubscriptionActive) {
+ break;
+ }
+ const orderHash = this.orderHashByExpirationRBTree.min();
+ this.orderHashByExpirationRBTree.remove(orderHash);
+ delete this.expiration[orderHash];
+ await callbackAsync(orderHash);
+ }
+ }
+}
diff --git a/packages/0x.js/src/order_watcher/order_state_watcher.ts b/packages/0x.js/src/order_watcher/order_state_watcher.ts
index bafd7a994..fd7496699 100644
--- a/packages/0x.js/src/order_watcher/order_state_watcher.ts
+++ b/packages/0x.js/src/order_watcher/order_state_watcher.ts
@@ -6,6 +6,7 @@ import {assert} from '../utils/assert';
import {utils} from '../utils/utils';
import {artifacts} from '../artifacts';
import {AbiDecoder} from '../utils/abi_decoder';
+import {intervalUtils} from '../utils/interval_utils';
import {OrderStateUtils} from '../utils/order_state_utils';
import {
LogEvent,
@@ -24,14 +25,14 @@ import {
ExchangeEvents,
TokenEvents,
ZeroExError,
+ ExchangeContractErrs,
} from '../types';
import {Web3Wrapper} from '../web3_wrapper';
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
import {OrderFilledCancelledLazyStore} from '../stores/order_filled_cancelled_lazy_store';
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
-
-const DEFAULT_NUM_CONFIRMATIONS = 0;
+import {ExpirationWatcher} from './expiration_watcher';
interface DependentOrderHashes {
[makerAddress: string]: {
@@ -52,10 +53,11 @@ interface OrderByOrderHash {
export class OrderStateWatcher {
private _orderByOrderHash: OrderByOrderHash = {};
private _dependentOrderHashes: DependentOrderHashes = {};
- private _callbackIfExistsAsync?: OnOrderStateChangeCallback;
+ private _callbackIfExists?: OnOrderStateChangeCallback;
private _eventWatcher: EventWatcher;
private _web3Wrapper: Web3Wrapper;
private _abiDecoder: AbiDecoder;
+ private _expirationWatcher: ExpirationWatcher;
private _orderStateUtils: OrderStateUtils;
private _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
private _balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore;
@@ -65,38 +67,53 @@ export class OrderStateWatcher {
) {
this._abiDecoder = abiDecoder;
this._web3Wrapper = web3Wrapper;
- const eventPollingIntervalMs = _.isUndefined(config) ? undefined : config.eventPollingIntervalMs;
- this._eventWatcher = new EventWatcher(web3Wrapper, eventPollingIntervalMs);
+ const pollingIntervalIfExistsMs = _.isUndefined(config) ? undefined : config.eventPollingIntervalMs;
+ this._eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalIfExistsMs);
this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(token);
this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(exchange);
this._orderStateUtils = new OrderStateUtils(
this._balanceAndProxyAllowanceLazyStore, this._orderFilledCancelledLazyStore,
);
+ const orderExpirationCheckingIntervalMsIfExists = _.isUndefined(config) ?
+ undefined :
+ config.orderExpirationCheckingIntervalMs;
+ const expirationMarginIfExistsMs = _.isUndefined(config) ?
+ undefined :
+ config.expirationMarginMs;
+ this._expirationWatcher = new ExpirationWatcher(
+ expirationMarginIfExistsMs, orderExpirationCheckingIntervalMsIfExists,
+ );
}
/**
* Add an order to the orderStateWatcher. Before the order is added, it's
* signature is verified.
* @param signedOrder The order you wish to start watching.
*/
- public addOrder(signedOrder: SignedOrder): void {
+ public async addOrderAsync(signedOrder: SignedOrder): Promise<void> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker);
this._orderByOrderHash[orderHash] = signedOrder;
- this.addToDependentOrderHashes(signedOrder, orderHash);
+ await this.addToDependentOrderHashesAsync(signedOrder, orderHash);
+ const expirationUnixTimestampMs = signedOrder.expirationUnixTimestampSec.times(1000);
+ this._expirationWatcher.addOrder(orderHash, expirationUnixTimestampMs);
}
/**
* Removes an order from the orderStateWatcher
* @param orderHash The orderHash of the order you wish to stop watching.
*/
- public removeOrder(orderHash: string): void {
+ public async removeOrderAsync(orderHash: string): Promise<void> {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const signedOrder = this._orderByOrderHash[orderHash];
if (_.isUndefined(signedOrder)) {
return; // noop
}
delete this._orderByOrderHash[orderHash];
+ const exchange = (this._orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper;
+ const zrxTokenAddress = await exchange.getZRXTokenAddressAsync();
+ this.removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
this.removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
+ this._expirationWatcher.removeOrder(orderHash);
}
/**
* Starts an orderStateWatcher subscription. The callback will be called every time a watched order's
@@ -106,23 +123,38 @@ export class OrderStateWatcher {
*/
public subscribe(callback: OnOrderStateChangeCallback): void {
assert.isFunction('callback', callback);
- if (!_.isUndefined(this._callbackIfExistsAsync)) {
+ if (!_.isUndefined(this._callbackIfExists)) {
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
}
- this._callbackIfExistsAsync = callback;
+ this._callbackIfExists = callback;
this._eventWatcher.subscribe(this._onEventWatcherCallbackAsync.bind(this));
+ this._expirationWatcher.subscribe(this._onOrderExpiredAsync.bind(this));
}
/**
* Ends an orderStateWatcher subscription.
*/
public unsubscribe(): void {
- if (_.isUndefined(this._callbackIfExistsAsync)) {
+ if (_.isUndefined(this._callbackIfExists)) {
throw new Error(ZeroExError.SubscriptionNotFound);
}
this._balanceAndProxyAllowanceLazyStore.deleteAll();
this._orderFilledCancelledLazyStore.deleteAll();
- delete this._callbackIfExistsAsync;
+ delete this._callbackIfExists;
this._eventWatcher.unsubscribe();
+ this._expirationWatcher.unsubscribe();
+ }
+ private async _onOrderExpiredAsync(orderHash: string): Promise<void> {
+ const orderState: OrderState = {
+ isValid: false,
+ orderHash,
+ error: ExchangeContractErrs.OrderFillExpired,
+ };
+ if (!_.isUndefined(this._orderByOrderHash[orderHash])) {
+ await this.removeOrderAsync(orderHash);
+ if (!_.isUndefined(this._callbackIfExists)) {
+ this._callbackIfExists(orderState);
+ }
+ }
}
private async _onEventWatcherCallbackAsync(log: LogEvent): Promise<void> {
const maybeDecodedLog = this._abiDecoder.tryToDecodeLogOrNoop(log);
@@ -204,13 +236,13 @@ export class OrderStateWatcher {
// Most of these calls will never reach the network because the data is fetched from stores
// and only updated when cache is invalidated
const orderState = await this._orderStateUtils.getOrderStateAsync(signedOrder);
- if (_.isUndefined(this._callbackIfExistsAsync)) {
+ if (_.isUndefined(this._callbackIfExists)) {
break; // Unsubscribe was called
}
- await this._callbackIfExistsAsync(orderState);
+ this._callbackIfExists(orderState);
}
}
- private addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string) {
+ private async addToDependentOrderHashesAsync(signedOrder: SignedOrder, orderHash: string): Promise<void> {
if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker])) {
this._dependentOrderHashes[signedOrder.maker] = {};
}
@@ -218,11 +250,17 @@ export class OrderStateWatcher {
this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress] = new Set();
}
this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress].add(orderHash);
+ const exchange = (this._orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper;
+ const zrxTokenAddress = await exchange.getZRXTokenAddressAsync();
+ if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress])) {
+ this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress] = new Set();
+ }
+ this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress].add(orderHash);
}
- private removeFromDependentOrderHashes(makerAddress: string, makerTokenAddress: string, orderHash: string) {
- this._dependentOrderHashes[makerAddress][makerTokenAddress].delete(orderHash);
- if (this._dependentOrderHashes[makerAddress][makerTokenAddress].size === 0) {
- delete this._dependentOrderHashes[makerAddress][makerTokenAddress];
+ private removeFromDependentOrderHashes(makerAddress: string, tokenAddress: string, orderHash: string) {
+ this._dependentOrderHashes[makerAddress][tokenAddress].delete(orderHash);
+ if (this._dependentOrderHashes[makerAddress][tokenAddress].size === 0) {
+ delete this._dependentOrderHashes[makerAddress][tokenAddress];
}
if (_.isEmpty(this._dependentOrderHashes[makerAddress])) {
delete this._dependentOrderHashes[makerAddress];
diff --git a/packages/0x.js/src/types.ts b/packages/0x.js/src/types.ts
index 71089f9a1..c3aabfd86 100644
--- a/packages/0x.js/src/types.ts
+++ b/packages/0x.js/src/types.ts
@@ -42,13 +42,8 @@ export type OrderValues = [BigNumber, BigNumber, BigNumber,
export type LogEvent = Web3.LogEntryEvent;
export type DecodedLogEvent<ArgsType> = Web3.DecodedLogEntryEvent<ArgsType>;
-export type EventCallbackAsync<ArgsType> = (err: null|Error, log?: DecodedLogEvent<ArgsType>) => Promise<void>;
-export type EventCallbackSync<ArgsType> = (err: null|Error, log?: DecodedLogEvent<ArgsType>) => void;
-export type EventCallback<ArgsType> = EventCallbackSync<ArgsType>|EventCallbackAsync<ArgsType>;
-
-export type EventWatcherCallbackSync = (log: LogEvent) => void;
-export type EventWatcherCallbackAsync = (log: LogEvent) => Promise<void>;
-export type EventWatcherCallback = EventWatcherCallbackSync|EventWatcherCallbackAsync;
+export type EventCallback<ArgsType> = (err: null|Error, log?: DecodedLogEvent<ArgsType>) => void;
+export type EventWatcherCallback = (log: LogEvent) => void;
export interface ExchangeContract extends Web3.ContractInstance {
isValidSignature: {
@@ -397,10 +392,15 @@ export interface JSONRPCPayload {
}
/*
- * eventPollingIntervalMs: How often to poll the Ethereum node for new events
+ * orderExpirationCheckingIntervalMs: How often to check for expired orders. Default: 50
+ * eventPollingIntervalMs: How often to poll the Ethereum node for new events. Defaults: 200
+ * expirationMarginMs: Amount of time before order expiry that you'd like to be notified
+ * of an orders expiration. Defaults: 0
*/
export interface OrderStateWatcherConfig {
+ orderExpirationCheckingIntervalMs?: number;
eventPollingIntervalMs?: number;
+ expirationMarginMs?: number;
}
/*
@@ -507,9 +507,7 @@ export interface OrderStateInvalid {
export type OrderState = OrderStateValid|OrderStateInvalid;
-export type OnOrderStateChangeCallbackSync = (orderState: OrderState) => void;
-export type OnOrderStateChangeCallbackAsync = (orderState: OrderState) => Promise<void>;
-export type OnOrderStateChangeCallback = OnOrderStateChangeCallbackAsync|OnOrderStateChangeCallbackSync;
+export type OnOrderStateChangeCallback = (orderState: OrderState) => void;
export interface TransactionReceipt {
blockHash: string;
diff --git a/packages/0x.js/src/utils/order_validation_utils.ts b/packages/0x.js/src/utils/order_validation_utils.ts
index f03703c4e..ed723e3d4 100644
--- a/packages/0x.js/src/utils/order_validation_utils.ts
+++ b/packages/0x.js/src/utils/order_validation_utils.ts
@@ -102,7 +102,7 @@ export class OrderValidationUtils {
if (order.takerTokenAmount.eq(unavailableTakerTokenAmount)) {
throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
}
- const currentUnixTimestampSec = utils.getCurrentUnixTimestamp();
+ const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
if (order.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
throw new Error(ExchangeContractErrs.OrderCancelExpired);
}
@@ -150,7 +150,7 @@ export class OrderValidationUtils {
}
}
private validateOrderNotExpiredOrThrow(expirationUnixTimestampSec: BigNumber) {
- const currentUnixTimestampSec = utils.getCurrentUnixTimestamp();
+ const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
if (expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
throw new Error(ExchangeContractErrs.OrderFillExpired);
}
diff --git a/packages/0x.js/src/utils/utils.ts b/packages/0x.js/src/utils/utils.ts
index 280f3e979..5370c3b4b 100644
--- a/packages/0x.js/src/utils/utils.ts
+++ b/packages/0x.js/src/utils/utils.ts
@@ -49,7 +49,10 @@ export const utils = {
const hashHex = ethUtil.bufferToHex(hashBuff);
return hashHex;
},
- getCurrentUnixTimestamp(): BigNumber {
- return new BigNumber(Date.now() / 1000);
+ getCurrentUnixTimestampSec(): BigNumber {
+ return new BigNumber(Date.now() / 1000).round();
+ },
+ getCurrentUnixTimestampMs(): BigNumber {
+ return new BigNumber(Date.now());
},
};
diff --git a/packages/0x.js/src/web3_wrapper.ts b/packages/0x.js/src/web3_wrapper.ts
index c937f9288..7bd8ea093 100644
--- a/packages/0x.js/src/web3_wrapper.ts
+++ b/packages/0x.js/src/web3_wrapper.ts
@@ -5,6 +5,17 @@ import promisify = require('es6-promisify');
import {ZeroExError, Artifact, TransactionReceipt} from './types';
import {Contract} from './contract';
+interface RawLogEntry {
+ logIndex: string|null;
+ transactionIndex: string|null;
+ transactionHash: string;
+ blockHash: string|null;
+ blockNumber: string|null;
+ address: string;
+ data: string;
+ topics: string[];
+}
+
export class Web3Wrapper {
private web3: Web3;
private defaults: Partial<Web3.TxData>;
@@ -39,7 +50,9 @@ export class Web3Wrapper {
}
public async getTransactionReceiptAsync(txHash: string): Promise<TransactionReceipt> {
const transactionReceipt = await promisify(this.web3.eth.getTransactionReceipt)(txHash);
- transactionReceipt.status = this.normalizeTxReceiptStatus(transactionReceipt.status);
+ if (!_.isNull(transactionReceipt)) {
+ transactionReceipt.status = this.normalizeTxReceiptStatus(transactionReceipt.status);
+ }
return transactionReceipt;
}
public getCurrentProvider(): Web3.Provider {
@@ -137,8 +150,9 @@ export class Web3Wrapper {
method: 'eth_getLogs',
params: [serializedFilter],
};
- const logs = await this.sendRawPayloadAsync(payload);
- return logs;
+ const rawLogs = await this.sendRawPayloadAsync<RawLogEntry[]>(payload);
+ const formattedLogs = _.map(rawLogs, this.formatLog.bind(this));
+ return formattedLogs;
}
private getContractInstance<A extends Web3.ContractInstance>(abi: Web3.ContractAbi, address: string): A {
const web3ContractInstance = this.web3.eth.contract(abi).at(address);
@@ -149,7 +163,7 @@ export class Web3Wrapper {
const networkId = await promisify(this.web3.version.getNetwork)();
return networkId;
}
- private async sendRawPayloadAsync(payload: Web3.JSONRPCRequestPayload): Promise<any> {
+ private async sendRawPayloadAsync<A>(payload: Web3.JSONRPCRequestPayload): Promise<A> {
const sendAsync = this.web3.currentProvider.sendAsync.bind(this.web3.currentProvider);
const response = await promisify(sendAsync)(payload);
const result = response.result;
@@ -169,4 +183,20 @@ export class Web3Wrapper {
return status;
}
}
+ private formatLog(rawLog: RawLogEntry): Web3.LogEntry {
+ const formattedLog = {
+ ...rawLog,
+ logIndex: this.hexToDecimal(rawLog.logIndex),
+ blockNumber: this.hexToDecimal(rawLog.blockNumber),
+ transactionIndex: this.hexToDecimal(rawLog.transactionIndex),
+ };
+ return formattedLog;
+ }
+ private hexToDecimal(hex: string|null): number|null {
+ if (_.isNull(hex)) {
+ return null;
+ }
+ const decimal = this.web3.toDecimal(hex);
+ return decimal;
+ }
}