aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md18
-rw-r--r--package-lock.json2
-rw-r--r--package.json2
-rw-r--r--src/contract_wrappers/contract_wrapper.ts29
-rw-r--r--src/contract_wrappers/exchange_wrapper.ts27
-rw-r--r--src/contract_wrappers/token_wrapper.ts15
-rw-r--r--src/index.ts2
-rw-r--r--src/types.ts16
-rw-r--r--src/utils/abi_decoder.ts5
-rw-r--r--src/utils/order_validation_utils.ts6
-rw-r--r--src/web3_wrapper.ts15
-rw-r--r--test/0x.js_test.ts6
-rw-r--r--test/ether_token_wrapper_test.ts1
-rw-r--r--test/exchange_transfer_simulator_test.ts4
-rw-r--r--test/exchange_wrapper_test.ts22
-rw-r--r--test/order_validation_test.ts38
-rw-r--r--test/token_wrapper_test.ts29
-rw-r--r--test/utils/fill_scenarios.ts2
18 files changed, 156 insertions, 83 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2aae081bf..255f413ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,22 @@
# CHANGELOG
-v0.21.0 - _TBD, 2017_
+v0.21.4 - _October 13, 2017_
+------------------------
+ * Made 0x.js more type-safe by making `getLogsAsync` and `subscribe/subscribeAsync` generics parametrized with arg type (#194)
+
+v0.21.3 - _October 12, 2017_
+------------------------
+ * Fixed a bug causing order fills to throw `INSUFFICIENT_TAKER_ALLOWANCE` (#193)
+
+v0.21.2 - _October 11, 2017_
+------------------------
+ * Exported `ContractEventArg` as a public type (#190)
+
+v0.21.1 - _October 11, 2017_
+------------------------
+ * Fixed a bug in subscriptions (#189)
+
+v0.21.0 - _October 10, 2017_
------------------------
* Complete rewrite of subscription logic (#182)
* Subscriptions no longer return historical logs. If you want them - use `getLogsAsync`
diff --git a/package-lock.json b/package-lock.json
index 1a46f7975..e11072e4a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "0x.js",
- "version": "0.21.0",
+ "version": "0.21.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 3bdaa59aa..c08a61463 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "0x.js",
- "version": "0.21.0",
+ "version": "0.21.4",
"description": "A javascript library for interacting with the 0x protocol",
"keywords": [
"0x.js",
diff --git a/src/contract_wrappers/contract_wrapper.ts b/src/contract_wrappers/contract_wrapper.ts
index f6ccfdee4..19dccc6f2 100644
--- a/src/contract_wrappers/contract_wrapper.ts
+++ b/src/contract_wrappers/contract_wrapper.ts
@@ -14,6 +14,7 @@ import {
IndexedFilterValues,
EventCallback,
BlockParamLiteral,
+ ContractEventArgs,
} from '../types';
import {constants} from '../utils/constants';
import {intervalUtils} from '../utils/interval_utils';
@@ -25,7 +26,7 @@ export class ContractWrapper {
private _blockAndLogStreamer: BlockAndLogStreamer|undefined;
private _blockAndLogStreamInterval: NodeJS.Timer;
private _filters: {[filterToken: string]: Web3.FilterObject};
- private _filterCallbacks: {[filterToken: string]: EventCallback};
+ private _filterCallbacks: {[filterToken: string]: EventCallback<ContractEventArgs>};
private _onLogAddedSubscriptionToken: string|undefined;
private _onLogRemovedSubscriptionToken: string|undefined;
constructor(web3Wrapper: Web3Wrapper, abiDecoder?: AbiDecoder) {
@@ -37,9 +38,9 @@ export class ContractWrapper {
this._onLogAddedSubscriptionToken = undefined;
this._onLogRemovedSubscriptionToken = undefined;
}
- protected _subscribe(address: string, eventName: ContractEvents,
- indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi,
- callback: EventCallback): string {
+ protected _subscribe<ArgsType extends ContractEventArgs>(
+ 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)) {
this._startBlockAndLogStream();
@@ -59,32 +60,32 @@ export class ContractWrapper {
this._stopBlockAndLogStream();
}
}
- protected async _getLogsAsync(address: string, eventName: ContractEvents, subscriptionOpts: SubscriptionOpts,
- indexFilterValues: IndexedFilterValues,
- abi: Web3.ContractAbi): Promise<LogWithDecodedArgs[]> {
+ 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);
const logs = await this._web3Wrapper.getLogsAsync(filter);
const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
return logsWithDecodedArguments;
}
- protected _tryToDecodeLogOrNoop(log: Web3.LogEntry): LogWithDecodedArgs|RawLog {
+ protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
+ log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog {
if (_.isUndefined(this._abiDecoder)) {
throw new Error(InternalZeroExError.NoAbiDecoder);
}
const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
return logWithDecodedArgs;
}
- protected async _instantiateContractIfExistsAsync<A extends Web3.ContractInstance>(artifact: Artifact,
- addressIfExists?: string,
- ): Promise<A> {
+ protected async _instantiateContractIfExistsAsync<ContractType extends Web3.ContractInstance>(
+ artifact: Artifact, addressIfExists?: string): Promise<ContractType> {
const contractInstance =
- await this._web3Wrapper.getContractInstanceFromArtifactAsync<A>(artifact, addressIfExists);
+ await this._web3Wrapper.getContractInstanceFromArtifactAsync<ContractType>(artifact, addressIfExists);
return contractInstance;
}
- private _onLogStateChanged(removed: boolean, log: Web3.LogEntry): void {
+ private _onLogStateChanged<ArgsType extends ContractEventArgs>(removed: boolean, log: Web3.LogEntry): void {
_.forEach(this._filters, (filter: Web3.FilterObject, filterToken: string) => {
if (filterUtils.matchesFilter(log, filter)) {
- const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs;
+ const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>;
const logEvent = {
...decodedLog,
removed,
diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts
index e7b4a437f..bc0ac0634 100644
--- a/src/contract_wrappers/exchange_wrapper.ts
+++ b/src/contract_wrappers/exchange_wrapper.ts
@@ -1,4 +1,5 @@
import * as _ from 'lodash';
+import * as Web3 from 'web3';
import * as BigNumber from 'bignumber.js';
import {schemas} from '0x-json-schemas';
import {Web3Wrapper} from '../web3_wrapper';
@@ -27,6 +28,8 @@ import {
OrderTransactionOpts,
RawLog,
EventCallback,
+ ExchangeContractEventArgs,
+ DecodedLogArgs,
} from '../types';
import {assert} from '../utils/assert';
import {utils} from '../utils/utils';
@@ -653,13 +656,14 @@ export class ExchangeWrapper extends ContractWrapper {
* @param callback Callback that gets called when a log is added/removed
* @return Subscription token used later to unsubscribe
*/
- public async subscribeAsync(eventName: ExchangeEvents, indexFilterValues: IndexedFilterValues,
- callback: EventCallback): Promise<string> {
+ public async subscribeAsync<ArgsType extends ExchangeContractEventArgs>(
+ eventName: ExchangeEvents, indexFilterValues: IndexedFilterValues,
+ callback: EventCallback<ArgsType>): Promise<string> {
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const exchangeContractAddress = await this.getContractAddressAsync();
- const subscriptionToken = this._subscribe(
+ const subscriptionToken = this._subscribe<ArgsType>(
exchangeContractAddress, eventName, indexFilterValues, artifacts.ExchangeArtifact.abi, callback,
);
this._activeSubscriptions.push(subscriptionToken);
@@ -681,13 +685,14 @@ export class ExchangeWrapper extends ContractWrapper {
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
- public async getLogsAsync(eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts,
- indexFilterValues: IndexedFilterValues): Promise<LogWithDecodedArgs[]> {
+ public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>(
+ eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts, indexFilterValues: IndexedFilterValues,
+ ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
assert.doesConformToSchema('subscriptionOpts', subscriptionOpts, schemas.subscriptionOptsSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const exchangeContractAddress = await this.getContractAddressAsync();
- const logs = await this._getLogsAsync(
+ const logs = await this._getLogsAsync<ArgsType>(
exchangeContractAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.ExchangeArtifact.abi,
);
return logs;
@@ -798,12 +803,14 @@ export class ExchangeWrapper extends ContractWrapper {
}
/**
* Checks if logs contain LogError, which is emmited by Exchange contract on transaction failure.
- * @param logsWithDecodedArgs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync`
+ * @param logs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync`
*/
- public throwLogErrorsAsErrors(logsWithDecodedArgs: LogWithDecodedArgs[]): void {
- const errLog = _.find(logsWithDecodedArgs, {event: ExchangeEvents.LogError});
+ public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs>|Web3.LogEntry>): void {
+ const errLog = _.find(logs, {
+ event: ExchangeEvents.LogError,
+ }) as LogWithDecodedArgs<LogErrorContractEventArgs>|undefined;
if (!_.isUndefined(errLog)) {
- const logArgs: LogErrorContractEventArgs = errLog.args as any;
+ const logArgs = errLog.args;
const errCode = logArgs.errorId.toNumber();
const errMessage = this._exchangeContractErrCodesToMsg[errCode];
throw new Error(errMessage);
diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts
index abd090f7e..8dc4e61c5 100644
--- a/src/contract_wrappers/token_wrapper.ts
+++ b/src/contract_wrappers/token_wrapper.ts
@@ -16,6 +16,7 @@ import {
MethodOpts,
LogWithDecodedArgs,
EventCallback,
+ TokenContractEventArgs,
} from '../types';
const ALLOWANCE_TO_ZERO_GAS_AMOUNT = 47155;
@@ -251,13 +252,14 @@ export class TokenWrapper extends ContractWrapper {
* @param callback Callback that gets called when a log is added/removed
* @return Subscription token used later to unsubscribe
*/
- public subscribe(tokenAddress: string, eventName: TokenEvents, indexFilterValues: IndexedFilterValues,
- callback: EventCallback): string {
+ public subscribe<ArgsType extends TokenContractEventArgs>(
+ tokenAddress: string, eventName: TokenEvents, indexFilterValues: IndexedFilterValues,
+ callback: EventCallback<ArgsType>): string {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
- const subscriptionToken = this._subscribe(
+ const subscriptionToken = this._subscribe<ArgsType>(
tokenAddress, eventName, indexFilterValues, artifacts.TokenArtifact.abi, callback,
);
this._activeSubscriptions.push(subscriptionToken);
@@ -280,13 +282,14 @@ export class TokenWrapper extends ContractWrapper {
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
- public async getLogsAsync(tokenAddress: string, eventName: TokenEvents, subscriptionOpts: SubscriptionOpts,
- indexFilterValues: IndexedFilterValues): Promise<LogWithDecodedArgs[]> {
+ public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
+ tokenAddress: string, eventName: TokenEvents, subscriptionOpts: SubscriptionOpts,
+ indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
assert.doesConformToSchema('subscriptionOpts', subscriptionOpts, schemas.subscriptionOptsSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- const logs = await this._getLogsAsync(
+ const logs = await this._getLogsAsync<ArgsType>(
tokenAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.TokenArtifact.abi,
);
return logs;
diff --git a/src/index.ts b/src/index.ts
index b9f50b0d6..249c20519 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -26,11 +26,11 @@ export {
ApprovalContractEventArgs,
TokenContractEventArgs,
ContractEventArgs,
+ ContractEventArg,
Web3Provider,
ZeroExConfig,
TransactionReceiptWithDecodedLogs,
LogWithDecodedArgs,
- DecodedLogArgs,
MethodOpts,
OrderTransactionOpts,
FilterObject,
diff --git a/src/types.ts b/src/types.ts
index 4d0b477dd..cb5fe4405 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -36,12 +36,12 @@ export type OrderAddresses = [string, string, string, string, string];
export type OrderValues = [BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber,
BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber];
-export interface LogEvent extends LogWithDecodedArgs {
+export interface LogEvent<ArgsType> extends LogWithDecodedArgs<ArgsType> {
removed: boolean;
}
-export type EventCallbackAsync = (log: LogEvent) => Promise<void>;
-export type EventCallbackSync = (log: LogEvent) => void;
-export type EventCallback = EventCallbackSync|EventCallbackAsync;
+export type EventCallbackAsync<ArgsType> = (log: LogEvent<ArgsType>) => Promise<void>;
+export type EventCallbackSync<ArgsType> = (log: LogEvent<ArgsType>) => void;
+export type EventCallback<ArgsType> = EventCallbackSync<ArgsType>|EventCallbackAsync<ArgsType>;
export interface ExchangeContract extends Web3.ContractInstance {
isValidSignature: {
callAsync: (signerAddressHex: string, dataHex: string, v: number, r: string, s: string,
@@ -414,15 +414,15 @@ export interface DecodedLogArgs {
[argName: string]: ContractEventArg;
}
-export interface DecodedArgs {
- args: DecodedLogArgs;
+export interface DecodedArgs<ArgsType> {
+ args: ArgsType;
event: string;
}
-export interface LogWithDecodedArgs extends Web3.LogEntry, DecodedArgs {}
+export interface LogWithDecodedArgs<ArgsType> extends Web3.LogEntry, DecodedArgs<ArgsType> {}
export interface TransactionReceiptWithDecodedLogs extends Web3.TransactionReceipt {
- logs: Array<LogWithDecodedArgs|Web3.LogEntry>;
+ logs: Array<LogWithDecodedArgs<DecodedLogArgs>|Web3.LogEntry>;
}
export interface Artifact {
diff --git a/src/utils/abi_decoder.ts b/src/utils/abi_decoder.ts
index 52b114c12..a6c45bee7 100644
--- a/src/utils/abi_decoder.ts
+++ b/src/utils/abi_decoder.ts
@@ -1,7 +1,7 @@
import * as Web3 from 'web3';
import * as _ from 'lodash';
import * as BigNumber from 'bignumber.js';
-import {AbiType, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes} from '../types';
+import {AbiType, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes, ContractEventArgs} from '../types';
import * as SolidityCoder from 'web3/lib/solidity/coder';
export class AbiDecoder {
@@ -11,7 +11,8 @@ export class AbiDecoder {
_.map(abiArrays, this.addABI.bind(this));
}
// This method can only decode logs from the 0x smart contracts
- public tryToDecodeLogOrNoop(log: Web3.LogEntry): LogWithDecodedArgs|RawLog {
+ public tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
+ log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog {
const methodId = log.topics[0];
const event = this.methodIds[methodId];
if (_.isUndefined(event)) {
diff --git a/src/utils/order_validation_utils.ts b/src/utils/order_validation_utils.ts
index 5d14602db..1d9aac884 100644
--- a/src/utils/order_validation_utils.ts
+++ b/src/utils/order_validation_utils.ts
@@ -102,11 +102,11 @@ export class OrderValidationUtils {
fillTakerTokenAmount: BigNumber.BigNumber, senderAddress: string, zrxTokenAddress: string): Promise<void> {
const fillMakerTokenAmount = this.getFillMakerTokenAmount(signedOrder, fillTakerTokenAmount);
await exchangeTradeEmulator.transferFromAsync(
- signedOrder.makerTokenAddress, signedOrder.maker, signedOrder.taker, fillMakerTokenAmount,
+ signedOrder.makerTokenAddress, signedOrder.maker, senderAddress, fillMakerTokenAmount,
TradeSide.Maker, TransferType.Trade,
);
await exchangeTradeEmulator.transferFromAsync(
- signedOrder.takerTokenAddress, signedOrder.taker, signedOrder.maker, fillTakerTokenAmount,
+ signedOrder.takerTokenAddress, senderAddress, signedOrder.maker, fillTakerTokenAmount,
TradeSide.Taker, TransferType.Trade,
);
await exchangeTradeEmulator.transferFromAsync(
@@ -114,7 +114,7 @@ export class OrderValidationUtils {
TransferType.Fee,
);
await exchangeTradeEmulator.transferFromAsync(
- zrxTokenAddress, signedOrder.taker, signedOrder.feeRecipient, signedOrder.takerFee, TradeSide.Taker,
+ zrxTokenAddress, senderAddress, signedOrder.feeRecipient, signedOrder.takerFee, TradeSide.Taker,
TransferType.Fee,
);
}
diff --git a/src/web3_wrapper.ts b/src/web3_wrapper.ts
index 9de75c809..ff5d25d9c 100644
--- a/src/web3_wrapper.ts
+++ b/src/web3_wrapper.ts
@@ -107,11 +107,24 @@ export class Web3Wrapper {
return addresses;
}
public async getLogsAsync(filter: Web3.FilterObject): Promise<Web3.LogEntry[]> {
+ let fromBlock = filter.fromBlock;
+ if (_.isNumber(fromBlock)) {
+ fromBlock = this.web3.toHex(fromBlock);
+ }
+ let toBlock = filter.toBlock;
+ if (_.isNumber(toBlock)) {
+ toBlock = this.web3.toHex(toBlock);
+ }
+ const serializedFilter = {
+ ...filter,
+ fromBlock,
+ toBlock,
+ };
const payload = {
jsonrpc: '2.0',
id: this.jsonRpcRequestId++,
method: 'eth_getLogs',
- params: [filter],
+ params: [serializedFilter],
};
const logs = await this.sendRawPayloadAsync(payload);
return logs;
diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts
index cc6b91e99..dd5dd19b1 100644
--- a/test/0x.js_test.ts
+++ b/test/0x.js_test.ts
@@ -4,7 +4,7 @@ import {chaiSetup} from './utils/chai_setup';
import 'mocha';
import * as BigNumber from 'bignumber.js';
import * as Sinon from 'sinon';
-import {ZeroEx, Order, ZeroExError, LogWithDecodedArgs} from '../src';
+import {ZeroEx, Order, ZeroExError, LogWithDecodedArgs, ApprovalContractEventArgs, TokenEvents} from '../src';
import {constants} from './utils/constants';
import {TokenUtils} from './utils/token_utils';
import {web3Factory} from './utils/web3_factory';
@@ -223,8 +223,8 @@ describe('ZeroEx library', () => {
const proxyAddress = await zeroEx.proxy.getContractAddressAsync();
const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
- const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs;
- expect(log.event).to.be.equal('Approval');
+ const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ApprovalContractEventArgs>;
+ expect(log.event).to.be.equal(TokenEvents.Approval);
expect(log.args._owner).to.be.equal(coinbase);
expect(log.args._spender).to.be.equal(proxyAddress);
expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
diff --git a/test/ether_token_wrapper_test.ts b/test/ether_token_wrapper_test.ts
index f50aac48b..389ec1619 100644
--- a/test/ether_token_wrapper_test.ts
+++ b/test/ether_token_wrapper_test.ts
@@ -3,7 +3,6 @@ import * as chai from 'chai';
import {chaiSetup} from './utils/chai_setup';
import * as Web3 from 'web3';
import * as BigNumber from 'bignumber.js';
-import promisify = require('es6-promisify');
import {web3Factory} from './utils/web3_factory';
import {ZeroEx, ZeroExError} from '../src';
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
diff --git a/test/exchange_transfer_simulator_test.ts b/test/exchange_transfer_simulator_test.ts
index 6ad2c007c..ee24f4fe4 100644
--- a/test/exchange_transfer_simulator_test.ts
+++ b/test/exchange_transfer_simulator_test.ts
@@ -1,12 +1,10 @@
import * as chai from 'chai';
import * as BigNumber from 'bignumber.js';
-import * as Web3 from 'web3';
import {chaiSetup} from './utils/chai_setup';
import {web3Factory} from './utils/web3_factory';
-import {ZeroEx, SignedOrder, ExchangeContractErrs, Token} from '../src';
+import {ZeroEx, ExchangeContractErrs, Token} from '../src';
import {TradeSide, TransferType} from '../src/types';
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
-import {FillScenarios} from './utils/fill_scenarios';
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
chaiSetup.configure();
diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts
index 8c5344b37..f3f16643e 100644
--- a/test/exchange_wrapper_test.ts
+++ b/test/exchange_wrapper_test.ts
@@ -3,8 +3,6 @@ import * as chai from 'chai';
import * as Web3 from 'web3';
import * as BigNumber from 'bignumber.js';
import {chaiSetup} from './utils/chai_setup';
-import ChaiBigNumber = require('chai-bignumber');
-import promisify = require('es6-promisify');
import {web3Factory} from './utils/web3_factory';
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
import {
@@ -16,15 +14,14 @@ import {
ContractEvent,
ExchangeContractErrs,
OrderCancellationRequest,
- LogFillContractEventArgs,
OrderFillRequest,
+ LogFillContractEventArgs,
+ LogCancelContractEventArgs,
LogEvent,
} from '../src';
import {DoneCallback, BlockParamLiteral} from '../src/types';
import {FillScenarios} from './utils/fill_scenarios';
import {TokenUtils} from './utils/token_utils';
-import {assert} from '../src/utils/assert';
-import {TokenTransferProxyWrapper} from '../src/contract_wrappers/token_transfer_proxy_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -650,7 +647,7 @@ describe('ExchangeWrapper', () => {
// Source: https://github.com/mochajs/mocha/issues/2407
it('Should receive the LogFill event when an order is filled', (done: DoneCallback) => {
(async () => {
- const callback = (logEvent: LogEvent) => {
+ const callback = (logEvent: LogEvent<LogFillContractEventArgs>) => {
expect(logEvent.event).to.be.equal(ExchangeEvents.LogFill);
done();
};
@@ -664,7 +661,7 @@ describe('ExchangeWrapper', () => {
});
it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => {
(async () => {
- const callback = (logEvent: LogEvent) => {
+ const callback = (logEvent: LogEvent<LogCancelContractEventArgs>) => {
expect(logEvent.event).to.be.equal(ExchangeEvents.LogCancel);
done();
};
@@ -676,7 +673,7 @@ describe('ExchangeWrapper', () => {
});
it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
(async () => {
- const callbackNeverToBeCalled = (logEvent: LogEvent) => {
+ const callbackNeverToBeCalled = (logEvent: LogEvent<LogFillContractEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
};
await zeroEx.exchange.subscribeAsync(
@@ -686,7 +683,7 @@ describe('ExchangeWrapper', () => {
const newProvider = web3Factory.getRpcProvider();
await zeroEx.setProviderAsync(newProvider);
- const callback = (logEvent: LogEvent) => {
+ const callback = (logEvent: LogEvent<LogFillContractEventArgs>) => {
expect(logEvent.event).to.be.equal(ExchangeEvents.LogFill);
done();
};
@@ -700,7 +697,7 @@ describe('ExchangeWrapper', () => {
});
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
(async () => {
- const callbackNeverToBeCalled = (logEvent: LogEvent) => {
+ const callbackNeverToBeCalled = (logEvent: LogEvent<LogFillContractEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
};
const subscriptionToken = await zeroEx.exchange.subscribeAsync(
@@ -810,11 +807,12 @@ describe('ExchangeWrapper', () => {
const indexFilterValues = {
maker: differentMakerAddress,
};
- const logs = await zeroEx.exchange.getLogsAsync(
+ const logs = await zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
eventName, subscriptionOpts, indexFilterValues,
);
expect(logs).to.have.length(1);
- expect(logs[0].args.maker).to.be.equal(differentMakerAddress);
+ const args = logs[0].args;
+ expect(args.maker).to.be.equal(differentMakerAddress);
});
});
});
diff --git a/test/order_validation_test.ts b/test/order_validation_test.ts
index 6f9388a69..784fa9ec4 100644
--- a/test/order_validation_test.ts
+++ b/test/order_validation_test.ts
@@ -1,7 +1,6 @@
import * as chai from 'chai';
import * as Web3 from 'web3';
import * as BigNumber from 'bignumber.js';
-import promisify = require('es6-promisify');
import * as Sinon from 'sinon';
import {chaiSetup} from './utils/chai_setup';
import {web3Factory} from './utils/web3_factory';
@@ -35,7 +34,6 @@ describe('OrderValidation', () => {
let orderValidationUtils: OrderValidationUtils;
const fillableAmount = new BigNumber(5);
const fillTakerAmount = new BigNumber(5);
- const shouldThrowOnInsufficientBalanceOrAllowance = false;
before(async () => {
web3 = web3Factory.create();
zeroEx = new ZeroEx(web3.currentProvider);
@@ -257,5 +255,41 @@ describe('OrderValidation', () => {
),
).to.be.true();
});
+ it('should call exchangeTransferSimulator.transferFrom with correct values for an open order', async () => {
+ const makerFee = new BigNumber(2);
+ const takerFee = new BigNumber(2);
+ const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
+ makerTokenAddress, takerTokenAddress, makerFee, takerFee,
+ makerAddress, ZeroEx.NULL_ADDRESS, fillableAmount, feeRecipient,
+ );
+ await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
+ exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
+ );
+ expect(transferFromAsync.callCount).to.be.equal(4);
+ expect(
+ transferFromAsync.getCall(0).calledWith(
+ makerTokenAddress, makerAddress, takerAddress, bigNumberMatch(fillableAmount),
+ TradeSide.Maker, TransferType.Trade,
+ ),
+ ).to.be.true();
+ expect(
+ transferFromAsync.getCall(1).calledWith(
+ takerTokenAddress, takerAddress, makerAddress, bigNumberMatch(fillableAmount),
+ TradeSide.Taker, TransferType.Trade,
+ ),
+ ).to.be.true();
+ expect(
+ transferFromAsync.getCall(2).calledWith(
+ zrxTokenAddress, makerAddress, feeRecipient, bigNumberMatch(makerFee),
+ TradeSide.Maker, TransferType.Fee,
+ ),
+ ).to.be.true();
+ expect(
+ transferFromAsync.getCall(3).calledWith(
+ zrxTokenAddress, takerAddress, feeRecipient, bigNumberMatch(takerFee),
+ TradeSide.Taker, TransferType.Fee,
+ ),
+ ).to.be.true();
+ });
});
});
diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts
index 50f2db2ac..f1f6543b7 100644
--- a/test/token_wrapper_test.ts
+++ b/test/token_wrapper_test.ts
@@ -14,6 +14,7 @@ import {
ContractEvent,
TransferContractEventArgs,
ApprovalContractEventArgs,
+ TokenContractEventArgs,
LogWithDecodedArgs,
LogEvent,
} from '../src';
@@ -357,9 +358,9 @@ describe('TokenWrapper', () => {
// Source: https://github.com/mochajs/mocha/issues/2407
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
(async () => {
- const callback = (logEvent: LogEvent) => {
+ const callback = (logEvent: LogEvent<TransferContractEventArgs>) => {
expect(logEvent).to.not.be.undefined();
- const args = logEvent.args as any as TransferContractEventArgs;
+ const args = logEvent.args;
expect(args._from).to.be.equal(coinbase);
expect(args._to).to.be.equal(addressWithoutFunds);
expect(args._value).to.be.bignumber.equal(transferAmount);
@@ -372,9 +373,9 @@ describe('TokenWrapper', () => {
});
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
(async () => {
- const callback = (logEvent: LogEvent) => {
+ const callback = (logEvent: LogEvent<ApprovalContractEventArgs>) => {
expect(logEvent).to.not.be.undefined();
- const args = logEvent.args as any as ApprovalContractEventArgs;
+ const args = logEvent.args;
expect(args._owner).to.be.equal(coinbase);
expect(args._spender).to.be.equal(addressWithoutFunds);
expect(args._value).to.be.bignumber.equal(allowanceAmount);
@@ -387,13 +388,13 @@ describe('TokenWrapper', () => {
});
it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
(async () => {
- const callbackNeverToBeCalled = (logEvent: LogEvent) => {
+ const callbackNeverToBeCalled = (logEvent: LogEvent<TransferContractEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
};
zeroEx.token.subscribe(
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled,
);
- const callbackToBeCalled = (logEvent: LogEvent) => {
+ const callbackToBeCalled = (logEvent: LogEvent<TransferContractEventArgs>) => {
done();
};
const newProvider = web3Factory.getRpcProvider();
@@ -406,7 +407,7 @@ describe('TokenWrapper', () => {
});
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
(async () => {
- const callbackNeverToBeCalled = (logEvent: LogEvent) => {
+ const callbackNeverToBeCalled = (logEvent: LogEvent<TokenContractEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
};
const subscriptionToken = zeroEx.token.subscribe(
@@ -435,14 +436,15 @@ describe('TokenWrapper', () => {
await zeroEx.awaitTransactionMinedAsync(txHash);
const eventName = TokenEvents.Approval;
const indexFilterValues = {};
- const logs = await zeroEx.token.getLogsAsync(
+ const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
tokenAddress, eventName, subscriptionOpts, indexFilterValues,
);
expect(logs).to.have.length(1);
+ const args = logs[0].args;
expect(logs[0].event).to.be.equal(eventName);
- expect(logs[0].args._owner).to.be.equal(coinbase);
- expect(logs[0].args._spender).to.be.equal(tokenTransferProxyAddress);
- expect(logs[0].args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
+ expect(args._owner).to.be.equal(coinbase);
+ expect(args._spender).to.be.equal(tokenTransferProxyAddress);
+ expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
});
it('should only get the logs with the correct event name', async () => {
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
@@ -463,11 +465,12 @@ describe('TokenWrapper', () => {
const indexFilterValues = {
_owner: coinbase,
};
- const logs = await zeroEx.token.getLogsAsync(
+ const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
tokenAddress, eventName, subscriptionOpts, indexFilterValues,
);
expect(logs).to.have.length(1);
- expect(logs[0].args._owner).to.be.equal(coinbase);
+ const args = logs[0].args;
+ expect(args._owner).to.be.equal(coinbase);
});
});
});
diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts
index e305759f6..c399c7bf4 100644
--- a/test/utils/fill_scenarios.ts
+++ b/test/utils/fill_scenarios.ts
@@ -91,7 +91,7 @@ export class FillScenarios {
}
private async increaseBalanceAndAllowanceAsync(
tokenAddress: string, address: string, amount: BigNumber.BigNumber): Promise<void> {
- if (amount.isZero()) {
+ if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
return; // noop
}
await Promise.all([