Apply prettier config
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
import {schemas, SchemaValidator} from '@0xproject/json-schemas';
|
||||
import {bigNumberConfigs, intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
||||
import { bigNumberConfigs, intervalUtils } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from './artifacts';
|
||||
import {EtherTokenWrapper} from './contract_wrappers/ether_token_wrapper';
|
||||
import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper';
|
||||
import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper';
|
||||
import {TokenTransferProxyWrapper} from './contract_wrappers/token_transfer_proxy_wrapper';
|
||||
import {TokenWrapper} from './contract_wrappers/token_wrapper';
|
||||
import {OrderStateWatcher} from './order_watcher/order_state_watcher';
|
||||
import {zeroExConfigSchema} from './schemas/zero_ex_config_schema';
|
||||
import { artifacts } from './artifacts';
|
||||
import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
|
||||
import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
|
||||
import { TokenRegistryWrapper } from './contract_wrappers/token_registry_wrapper';
|
||||
import { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper';
|
||||
import { TokenWrapper } from './contract_wrappers/token_wrapper';
|
||||
import { OrderStateWatcher } from './order_watcher/order_state_watcher';
|
||||
import { zeroExConfigSchema } from './schemas/zero_ex_config_schema';
|
||||
import {
|
||||
ECSignature,
|
||||
Order,
|
||||
@@ -22,12 +22,12 @@ import {
|
||||
ZeroExConfig,
|
||||
ZeroExError,
|
||||
} from './types';
|
||||
import {AbiDecoder} from './utils/abi_decoder';
|
||||
import {assert} from './utils/assert';
|
||||
import {constants} from './utils/constants';
|
||||
import {decorators} from './utils/decorators';
|
||||
import {signatureUtils} from './utils/signature_utils';
|
||||
import {utils} from './utils/utils';
|
||||
import { AbiDecoder } from './utils/abi_decoder';
|
||||
import { assert } from './utils/assert';
|
||||
import { constants } from './utils/constants';
|
||||
import { decorators } from './utils/decorators';
|
||||
import { signatureUtils } from './utils/signature_utils';
|
||||
import { utils } from './utils/utils';
|
||||
|
||||
// Customize our BigNumber instances
|
||||
bigNumberConfigs.configure();
|
||||
@@ -161,7 +161,7 @@ export class ZeroEx {
|
||||
* @return The resulting orderHash from hashing the supplied order.
|
||||
*/
|
||||
@decorators.syncZeroExErrorHandler
|
||||
public static getOrderHashHex(order: Order|SignedOrder): string {
|
||||
public static getOrderHashHex(order: Order | SignedOrder): string {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
const orderHashHex = utils.getOrderHashHex(order);
|
||||
return orderHashHex;
|
||||
@@ -188,12 +188,7 @@ export class ZeroEx {
|
||||
config.networkId,
|
||||
config.tokenTransferProxyContractAddress,
|
||||
);
|
||||
this.token = new TokenWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
this._abiDecoder,
|
||||
this.proxy,
|
||||
);
|
||||
this.token = new TokenWrapper(this._web3Wrapper, config.networkId, this._abiDecoder, this.proxy);
|
||||
this.exchange = new ExchangeWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
@@ -202,13 +197,17 @@ export class ZeroEx {
|
||||
config.exchangeContractAddress,
|
||||
);
|
||||
this.tokenRegistry = new TokenRegistryWrapper(
|
||||
this._web3Wrapper, config.networkId, config.tokenRegistryContractAddress,
|
||||
);
|
||||
this.etherToken = new EtherTokenWrapper(
|
||||
this._web3Wrapper, config.networkId, this._abiDecoder, this.token,
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
config.tokenRegistryContractAddress,
|
||||
);
|
||||
this.etherToken = new EtherTokenWrapper(this._web3Wrapper, config.networkId, this._abiDecoder, this.token);
|
||||
this.orderStateWatcher = new OrderStateWatcher(
|
||||
this._web3Wrapper, this._abiDecoder, this.token, this.exchange, config.orderWatcherConfig,
|
||||
this._web3Wrapper,
|
||||
this._abiDecoder,
|
||||
this.token,
|
||||
this.exchange,
|
||||
config.orderWatcherConfig,
|
||||
);
|
||||
}
|
||||
/**
|
||||
@@ -291,35 +290,39 @@ export class ZeroEx {
|
||||
* @return Transaction receipt with decoded log args.
|
||||
*/
|
||||
public async awaitTransactionMinedAsync(
|
||||
txHash: string, pollingIntervalMs = 1000, timeoutMs?: number): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
txHash: string,
|
||||
pollingIntervalMs = 1000,
|
||||
timeoutMs?: number,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
let timeoutExceeded = false;
|
||||
if (timeoutMs) {
|
||||
setTimeout(() => timeoutExceeded = true, timeoutMs);
|
||||
setTimeout(() => (timeoutExceeded = true), timeoutMs);
|
||||
}
|
||||
|
||||
const txReceiptPromise = new Promise(
|
||||
(resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => {
|
||||
const intervalId = intervalUtils.setAsyncExcludingInterval(async () => {
|
||||
if (timeoutExceeded) {
|
||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
||||
return reject(ZeroExError.TransactionMiningTimeout);
|
||||
}
|
||||
const intervalId = intervalUtils.setAsyncExcludingInterval(async () => {
|
||||
if (timeoutExceeded) {
|
||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
||||
return reject(ZeroExError.TransactionMiningTimeout);
|
||||
}
|
||||
|
||||
const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
|
||||
if (!_.isNull(transactionReceipt)) {
|
||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
||||
const logsWithDecodedArgs = _.map(
|
||||
transactionReceipt.logs,
|
||||
this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder),
|
||||
);
|
||||
const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
|
||||
...transactionReceipt,
|
||||
logs: logsWithDecodedArgs,
|
||||
};
|
||||
resolve(transactionReceiptWithDecodedLogArgs);
|
||||
}
|
||||
}, pollingIntervalMs);
|
||||
});
|
||||
const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
|
||||
if (!_.isNull(transactionReceipt)) {
|
||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
||||
const logsWithDecodedArgs = _.map(
|
||||
transactionReceipt.logs,
|
||||
this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder),
|
||||
);
|
||||
const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
|
||||
...transactionReceipt,
|
||||
logs: logsWithDecodedArgs,
|
||||
};
|
||||
resolve(transactionReceiptWithDecodedLogArgs);
|
||||
}
|
||||
}, pollingIntervalMs);
|
||||
},
|
||||
);
|
||||
|
||||
return txReceiptPromise;
|
||||
}
|
||||
|
@@ -5,14 +5,14 @@ import * as TokenArtifact from './artifacts/Token.json';
|
||||
import * as TokenRegistryArtifact from './artifacts/TokenRegistry.json';
|
||||
import * as TokenTransferProxyArtifact from './artifacts/TokenTransferProxy.json';
|
||||
import * as ZRXArtifact from './artifacts/ZRX.json';
|
||||
import {Artifact} from './types';
|
||||
import { Artifact } from './types';
|
||||
|
||||
export const artifacts = {
|
||||
ZRXArtifact: ZRXArtifact as any as Artifact,
|
||||
DummyTokenArtifact: DummyTokenArtifact as any as Artifact,
|
||||
TokenArtifact: TokenArtifact as any as Artifact,
|
||||
ExchangeArtifact: ExchangeArtifact as any as Artifact,
|
||||
EtherTokenArtifact: EtherTokenArtifact as any as Artifact,
|
||||
TokenRegistryArtifact: TokenRegistryArtifact as any as Artifact,
|
||||
TokenTransferProxyArtifact: TokenTransferProxyArtifact as any as Artifact,
|
||||
ZRXArtifact: (ZRXArtifact as any) as Artifact,
|
||||
DummyTokenArtifact: (DummyTokenArtifact as any) as Artifact,
|
||||
TokenArtifact: (TokenArtifact as any) as Artifact,
|
||||
ExchangeArtifact: (ExchangeArtifact as any) as Artifact,
|
||||
EtherTokenArtifact: (EtherTokenArtifact as any) as Artifact,
|
||||
TokenRegistryArtifact: (TokenRegistryArtifact as any) as Artifact,
|
||||
TokenTransferProxyArtifact: (TokenTransferProxyArtifact as any) as Artifact,
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
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';
|
||||
|
||||
@@ -17,11 +17,13 @@ import {
|
||||
RawLog,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {constants} from '../utils/constants';
|
||||
import {filterUtils} from '../utils/filter_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,12 +36,14 @@ export class ContractWrapper {
|
||||
protected _web3Wrapper: Web3Wrapper;
|
||||
private _networkId: number;
|
||||
private _abiDecoder?: AbiDecoder;
|
||||
private _blockAndLogStreamerIfExists: 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;
|
||||
@@ -71,8 +75,12 @@ 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._blockAndLogStreamerIfExists)) {
|
||||
this._startBlockAndLogStream();
|
||||
@@ -83,15 +91,20 @@ export class ContractWrapper {
|
||||
return filterToken;
|
||||
}
|
||||
protected async _getLogsAsync<ArgsType extends ContractEventArgs>(
|
||||
address: string, eventName: ContractEvents, blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
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);
|
||||
}
|
||||
@@ -99,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)) {
|
||||
@@ -114,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 {
|
||||
@@ -153,7 +165,8 @@ export class ContractWrapper {
|
||||
const 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,
|
||||
);
|
||||
let isRemoved = false;
|
||||
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
|
||||
@@ -179,7 +192,7 @@ export class ContractWrapper {
|
||||
// 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);
|
||||
await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block);
|
||||
}
|
||||
} catch (err) {
|
||||
const filterTokens = _.keys(this._filterCallbacks);
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import { artifacts } from '../artifacts';
|
||||
import {
|
||||
BlockRange,
|
||||
EtherTokenContractEventArgs,
|
||||
@@ -14,19 +14,21 @@ import {
|
||||
TransactionOpts,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {assert} from '../utils/assert';
|
||||
import { AbiDecoder } from '../utils/abi_decoder';
|
||||
import { assert } from '../utils/assert';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {EtherTokenContract} from './generated/ether_token';
|
||||
import {TokenWrapper} from './token_wrapper';
|
||||
import { ContractWrapper } from './contract_wrapper';
|
||||
import { EtherTokenContract } from './generated/ether_token';
|
||||
import { TokenWrapper } from './token_wrapper';
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
|
||||
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
|
||||
*/
|
||||
export class EtherTokenWrapper extends ContractWrapper {
|
||||
private _etherTokenContractsByAddress: {[address: string]: EtherTokenContract} = {};
|
||||
private _etherTokenContractsByAddress: {
|
||||
[address: string]: EtherTokenContract;
|
||||
} = {};
|
||||
private _tokenWrapper: TokenWrapper;
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder, tokenWrapper: TokenWrapper) {
|
||||
super(web3Wrapper, networkId, abiDecoder);
|
||||
@@ -43,7 +45,10 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async depositAsync(
|
||||
etherTokenAddress: string, amountInWei: BigNumber, depositor: string, txOpts: TransactionOpts = {},
|
||||
etherTokenAddress: string,
|
||||
amountInWei: BigNumber,
|
||||
depositor: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||
await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
|
||||
@@ -70,7 +75,10 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async withdrawAsync(
|
||||
etherTokenAddress: string, amountInWei: BigNumber, withdrawer: string, txOpts: TransactionOpts = {},
|
||||
etherTokenAddress: string,
|
||||
amountInWei: BigNumber,
|
||||
withdrawer: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||
await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
|
||||
@@ -96,14 +104,21 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends EtherTokenContractEventArgs>(
|
||||
etherTokenAddress: string, eventName: EtherTokenEvents, blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
etherTokenAddress: string,
|
||||
eventName: EtherTokenEvents,
|
||||
blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const logs = await this._getLogsAsync<ArgsType>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues, artifacts.EtherTokenArtifact.abi,
|
||||
etherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
artifacts.EtherTokenArtifact.abi,
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
@@ -117,14 +132,21 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
* @return Subscription token used later to unsubscribe
|
||||
*/
|
||||
public subscribe<ArgsType extends EtherTokenContractEventArgs>(
|
||||
etherTokenAddress: string, eventName: EtherTokenEvents, indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>): string {
|
||||
etherTokenAddress: string,
|
||||
eventName: EtherTokenEvents,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>,
|
||||
): string {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const subscriptionToken = this._subscribe<ArgsType>(
|
||||
etherTokenAddress, eventName, indexFilterValues, artifacts.EtherTokenArtifact.abi, callback,
|
||||
etherTokenAddress,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
artifacts.EtherTokenArtifact.abi,
|
||||
callback,
|
||||
);
|
||||
return subscriptionToken;
|
||||
}
|
||||
@@ -151,7 +173,8 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
return etherTokenContract;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.EtherTokenArtifact, etherTokenAddress,
|
||||
artifacts.EtherTokenArtifact,
|
||||
etherTokenAddress,
|
||||
);
|
||||
const contractInstance = new EtherTokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
||||
etherTokenContract = contractInstance;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import { artifacts } from '../artifacts';
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
@@ -28,16 +28,16 @@ import {
|
||||
SignedOrder,
|
||||
ValidateOrderFillableOpts,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {assert} from '../utils/assert';
|
||||
import {decorators} from '../utils/decorators';
|
||||
import {ExchangeTransferSimulator} from '../utils/exchange_transfer_simulator';
|
||||
import {OrderValidationUtils} from '../utils/order_validation_utils';
|
||||
import {utils} from '../utils/utils';
|
||||
import { AbiDecoder } from '../utils/abi_decoder';
|
||||
import { assert } from '../utils/assert';
|
||||
import { decorators } from '../utils/decorators';
|
||||
import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator';
|
||||
import { OrderValidationUtils } from '../utils/order_validation_utils';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {ExchangeContract} from './generated/exchange';
|
||||
import {TokenWrapper} from './token_wrapper';
|
||||
import { ContractWrapper } from './contract_wrapper';
|
||||
import { ExchangeContract } from './generated/exchange';
|
||||
import { TokenWrapper } from './token_wrapper';
|
||||
|
||||
const SHOULD_VALIDATE_BY_DEFAULT = true;
|
||||
|
||||
@@ -81,8 +81,13 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
];
|
||||
return [orderAddresses, orderValues];
|
||||
}
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder,
|
||||
tokenWrapper: TokenWrapper, contractAddressIfExists?: string) {
|
||||
constructor(
|
||||
web3Wrapper: Web3Wrapper,
|
||||
networkId: number,
|
||||
abiDecoder: AbiDecoder,
|
||||
tokenWrapper: TokenWrapper,
|
||||
contractAddressIfExists?: string,
|
||||
) {
|
||||
super(web3Wrapper, networkId, abiDecoder);
|
||||
this._tokenWrapper = tokenWrapper;
|
||||
this._orderValidationUtils = new OrderValidationUtils(this);
|
||||
@@ -97,14 +102,14 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return The amount of the order (in taker tokens) that has either been filled or cancelled.
|
||||
*/
|
||||
public async getUnavailableTakerAmountAsync(orderHash: string,
|
||||
methodOpts?: MethodOpts): Promise<BigNumber> {
|
||||
public async getUnavailableTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> {
|
||||
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
||||
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||
let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(
|
||||
orderHash, defaultBlock,
|
||||
orderHash,
|
||||
defaultBlock,
|
||||
);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount);
|
||||
@@ -163,24 +168,32 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
public async fillOrderAsync(
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
||||
SHOULD_VALIDATE_BY_DEFAULT :
|
||||
orderTransactionOpts.shouldValidate;
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
|
||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
|
||||
@@ -219,30 +232,42 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async fillOrdersUpToAsync(signedOrders: SignedOrder[], fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
public async fillOrdersUpToAsync(
|
||||
signedOrders: SignedOrder[],
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress);
|
||||
assert.hasAtMostOneUniqueValue(takerTokenAddresses,
|
||||
ExchangeContractErrs.MultipleTakerTokensInFillUpToDisallowed);
|
||||
assert.hasAtMostOneUniqueValue(
|
||||
takerTokenAddresses,
|
||||
ExchangeContractErrs.MultipleTakerTokensInFillUpToDisallowed,
|
||||
);
|
||||
const exchangeContractAddresses = _.map(signedOrders, signedOrder => signedOrder.exchangeContractAddress);
|
||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
|
||||
assert.hasAtMostOneUniqueValue(
|
||||
exchangeContractAddresses,
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||
);
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
||||
SHOULD_VALIDATE_BY_DEFAULT :
|
||||
orderTransactionOpts.shouldValidate;
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
for (const signedOrder of signedOrders) {
|
||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,29 +325,36 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async batchFillOrdersAsync(orderFillRequests: OrderFillRequest[],
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
public async batchFillOrdersAsync(
|
||||
orderFillRequests: OrderFillRequest[],
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema);
|
||||
const exchangeContractAddresses = _.map(
|
||||
orderFillRequests,
|
||||
orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
|
||||
);
|
||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
|
||||
assert.hasAtMostOneUniqueValue(
|
||||
exchangeContractAddresses,
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||
);
|
||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
||||
SHOULD_VALIDATE_BY_DEFAULT :
|
||||
orderTransactionOpts.shouldValidate;
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
for (const orderFillRequest of orderFillRequests) {
|
||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount,
|
||||
takerAddress, zrxTokenAddress,
|
||||
exchangeTradeEmulator,
|
||||
orderFillRequest.signedOrder,
|
||||
orderFillRequest.takerTokenFillAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -373,23 +405,31 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async fillOrKillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
public async fillOrKillOrderAsync(
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
||||
SHOULD_VALIDATE_BY_DEFAULT :
|
||||
orderTransactionOpts.shouldValidate;
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
|
||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
|
||||
@@ -418,33 +458,39 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async batchFillOrKillAsync(orderFillRequests: OrderFillRequest[],
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
assert.doesConformToSchema('orderFillRequests', orderFillRequests,
|
||||
schemas.orderFillRequestsSchema);
|
||||
public async batchFillOrKillAsync(
|
||||
orderFillRequests: OrderFillRequest[],
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema);
|
||||
const exchangeContractAddresses = _.map(
|
||||
orderFillRequests,
|
||||
orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
|
||||
);
|
||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
|
||||
assert.hasAtMostOneUniqueValue(
|
||||
exchangeContractAddresses,
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||
);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
if (_.isEmpty(orderFillRequests)) {
|
||||
throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
}
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
||||
SHOULD_VALIDATE_BY_DEFAULT :
|
||||
orderTransactionOpts.shouldValidate;
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
for (const orderFillRequest of orderFillRequests) {
|
||||
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount,
|
||||
takerAddress, zrxTokenAddress,
|
||||
exchangeTradeEmulator,
|
||||
orderFillRequest.signedOrder,
|
||||
orderFillRequest.takerTokenFillAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -460,8 +506,9 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
});
|
||||
|
||||
// We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
|
||||
const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] =
|
||||
_.unzip<any>(orderAddressesValuesAndTakerTokenFillAmounts);
|
||||
const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] = _.unzip<any>(
|
||||
orderAddressesValuesAndTakerTokenFillAmounts,
|
||||
);
|
||||
const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync(
|
||||
orderAddresses,
|
||||
orderValues,
|
||||
@@ -486,23 +533,28 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async cancelOrderAsync(order: Order|SignedOrder,
|
||||
cancelTakerTokenAmount: BigNumber,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
public async cancelOrderAsync(
|
||||
order: Order | SignedOrder,
|
||||
cancelTakerTokenAmount: BigNumber,
|
||||
orderTransactionOpts: OrderTransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
assert.isValidBaseUnitAmount('takerTokenCancelAmount', cancelTakerTokenAmount);
|
||||
await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
||||
SHOULD_VALIDATE_BY_DEFAULT :
|
||||
orderTransactionOpts.shouldValidate;
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
const orderHash = utils.getOrderHashHex(order);
|
||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||
order, cancelTakerTokenAmount, unavailableTakerTokenAmount);
|
||||
order,
|
||||
cancelTakerTokenAmount,
|
||||
unavailableTakerTokenAmount,
|
||||
);
|
||||
}
|
||||
|
||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
|
||||
@@ -527,33 +579,40 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async batchCancelOrdersAsync(orderCancellationRequests: OrderCancellationRequest[],
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
assert.doesConformToSchema('orderCancellationRequests', orderCancellationRequests,
|
||||
schemas.orderCancellationRequestsSchema);
|
||||
public async batchCancelOrdersAsync(
|
||||
orderCancellationRequests: OrderCancellationRequest[],
|
||||
orderTransactionOpts: OrderTransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.doesConformToSchema(
|
||||
'orderCancellationRequests',
|
||||
orderCancellationRequests,
|
||||
schemas.orderCancellationRequestsSchema,
|
||||
);
|
||||
const exchangeContractAddresses = _.map(
|
||||
orderCancellationRequests,
|
||||
orderCancellationRequest => orderCancellationRequest.order.exchangeContractAddress,
|
||||
);
|
||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
|
||||
assert.hasAtMostOneUniqueValue(
|
||||
exchangeContractAddresses,
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||
);
|
||||
const makers = _.map(orderCancellationRequests, cancellationRequest => cancellationRequest.order.maker);
|
||||
assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
|
||||
const maker = makers[0];
|
||||
await assert.isSenderAddressAsync('maker', maker, this._web3Wrapper);
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
||||
SHOULD_VALIDATE_BY_DEFAULT :
|
||||
orderTransactionOpts.shouldValidate;
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
for (const orderCancellationRequest of orderCancellationRequests) {
|
||||
const orderHash = utils.getOrderHashHex(orderCancellationRequest.order);
|
||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||
orderCancellationRequest.order, orderCancellationRequest.takerTokenCancelAmount,
|
||||
orderCancellationRequest.order,
|
||||
orderCancellationRequest.takerTokenCancelAmount,
|
||||
unavailableTakerTokenAmount,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
if (_.isEmpty(orderCancellationRequests)) {
|
||||
throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
@@ -566,8 +625,9 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
];
|
||||
});
|
||||
// We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
|
||||
const [orderAddresses, orderValues, cancelTakerTokenAmounts] =
|
||||
_.unzip<any>(orderAddressesValuesAndTakerTokenCancelAmounts);
|
||||
const [orderAddresses, orderValues, cancelTakerTokenAmounts] = _.unzip<any>(
|
||||
orderAddressesValuesAndTakerTokenCancelAmounts,
|
||||
);
|
||||
const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync(
|
||||
orderAddresses,
|
||||
orderValues,
|
||||
@@ -589,14 +649,20 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Subscription token used later to unsubscribe
|
||||
*/
|
||||
public subscribe<ArgsType extends ExchangeContractEventArgs>(
|
||||
eventName: ExchangeEvents, indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>): string {
|
||||
eventName: ExchangeEvents,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>,
|
||||
): string {
|
||||
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const exchangeContractAddress = this.getContractAddress();
|
||||
const subscriptionToken = this._subscribe<ArgsType>(
|
||||
exchangeContractAddress, eventName, indexFilterValues, artifacts.ExchangeArtifact.abi, callback,
|
||||
exchangeContractAddress,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
artifacts.ExchangeArtifact.abi,
|
||||
callback,
|
||||
);
|
||||
return subscriptionToken;
|
||||
}
|
||||
@@ -622,14 +688,20 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>(
|
||||
eventName: ExchangeEvents, blockRange: BlockRange, indexFilterValues: IndexedFilterValues,
|
||||
eventName: ExchangeEvents,
|
||||
blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const exchangeContractAddress = this.getContractAddress();
|
||||
const logs = await this._getLogsAsync<ArgsType>(
|
||||
exchangeContractAddress, eventName, blockRange, indexFilterValues, artifacts.ExchangeArtifact.abi,
|
||||
exchangeContractAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
artifacts.ExchangeArtifact.abi,
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
@@ -652,14 +724,18 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* to validate for.
|
||||
*/
|
||||
public async validateOrderFillableOrThrowAsync(
|
||||
signedOrder: SignedOrder, opts?: ValidateOrderFillableOpts,
|
||||
signedOrder: SignedOrder,
|
||||
opts?: ValidateOrderFillableOpts,
|
||||
): Promise<void> {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const expectedFillTakerTokenAmount = !_.isUndefined(opts) ? opts.expectedFillTakerTokenAmount : undefined;
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
await this._orderValidationUtils.validateOrderFillableOrThrowAsync(
|
||||
exchangeTradeEmulator, signedOrder, zrxTokenAddress, expectedFillTakerTokenAmount,
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
zrxTokenAddress,
|
||||
expectedFillTakerTokenAmount,
|
||||
);
|
||||
}
|
||||
/**
|
||||
@@ -670,16 +746,23 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param takerAddress The user Ethereum address who would like to fill this order.
|
||||
* Must be available via the supplied Web3.Provider passed to 0x.js.
|
||||
*/
|
||||
public async validateFillOrderThrowIfInvalidAsync(signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string): Promise<void> {
|
||||
public async validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
): Promise<void> {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Checks if cancelling a given order will succeed and throws an informative error if it won't.
|
||||
@@ -688,13 +771,18 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel.
|
||||
*/
|
||||
public async validateCancelOrderThrowIfInvalidAsync(
|
||||
order: Order, cancelTakerTokenAmount: BigNumber): Promise<void> {
|
||||
order: Order,
|
||||
cancelTakerTokenAmount: BigNumber,
|
||||
): Promise<void> {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount);
|
||||
const orderHash = utils.getOrderHashHex(order);
|
||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||
order, cancelTakerTokenAmount, unavailableTakerTokenAmount);
|
||||
order,
|
||||
cancelTakerTokenAmount,
|
||||
unavailableTakerTokenAmount,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Checks if calling fillOrKill on a given order will succeed and throws an informative error if it won't.
|
||||
@@ -704,16 +792,23 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param takerAddress The user Ethereum address who would like to fill this order.
|
||||
* Must be available via the supplied Web3.Provider passed to 0x.js.
|
||||
*/
|
||||
public async validateFillOrKillOrderThrowIfInvalidAsync(signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string): Promise<void> {
|
||||
public async validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
): Promise<void> {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Checks if rounding error will be > 0.1% when computing makerTokenAmount by doing:
|
||||
@@ -724,15 +819,19 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param takerTokenAmount The order size on the taker side
|
||||
* @param makerTokenAmount The order size on the maker side
|
||||
*/
|
||||
public async isRoundingErrorAsync(fillTakerTokenAmount: BigNumber,
|
||||
takerTokenAmount: BigNumber,
|
||||
makerTokenAmount: BigNumber): Promise<boolean> {
|
||||
public async isRoundingErrorAsync(
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
takerTokenAmount: BigNumber,
|
||||
makerTokenAmount: BigNumber,
|
||||
): Promise<boolean> {
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
assert.isValidBaseUnitAmount('takerTokenAmount', takerTokenAmount);
|
||||
assert.isValidBaseUnitAmount('makerTokenAmount', makerTokenAmount);
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const isRoundingError = await exchangeInstance.isRoundingError.callAsync(
|
||||
fillTakerTokenAmount, takerTokenAmount, makerTokenAmount,
|
||||
fillTakerTokenAmount,
|
||||
takerTokenAmount,
|
||||
makerTokenAmount,
|
||||
);
|
||||
return isRoundingError;
|
||||
}
|
||||
@@ -740,10 +839,10 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* Checks if logs contain LogError, which is emmited by Exchange contract on transaction failure.
|
||||
* @param logs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync`
|
||||
*/
|
||||
public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs>|Web3.LogEntry>): void {
|
||||
public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs> | Web3.LogEntry>): void {
|
||||
const errLog = _.find(logs, {
|
||||
event: ExchangeEvents.LogError,
|
||||
}) as LogWithDecodedArgs<LogErrorContractEventArgs>|undefined;
|
||||
}) as LogWithDecodedArgs<LogErrorContractEventArgs> | undefined;
|
||||
if (!_.isUndefined(errLog)) {
|
||||
const logArgs = errLog.args;
|
||||
const errCode = logArgs.errorId.toNumber();
|
||||
@@ -756,17 +855,18 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @return Address of ZRX token
|
||||
*/
|
||||
public getZRXTokenAddress(): string {
|
||||
const contractAddress = this._getContractAddress(
|
||||
artifacts.ZRXArtifact, this._zrxContractAddressIfExists,
|
||||
);
|
||||
const contractAddress = this._getContractAddress(artifacts.ZRXArtifact, this._zrxContractAddressIfExists);
|
||||
return contractAddress;
|
||||
}
|
||||
private _invalidateContractInstances(): void {
|
||||
this.unsubscribeAll();
|
||||
delete this._exchangeContractIfExists;
|
||||
}
|
||||
private async _isValidSignatureUsingContractCallAsync(dataHex: string, ecSignature: ECSignature,
|
||||
signerAddressHex: string): Promise<boolean> {
|
||||
private async _isValidSignatureUsingContractCallAsync(
|
||||
dataHex: string,
|
||||
ecSignature: ECSignature,
|
||||
signerAddressHex: string,
|
||||
): Promise<boolean> {
|
||||
assert.isHexString('dataHex', dataHex);
|
||||
assert.doesConformToSchema('ecSignature', ecSignature, schemas.ecSignatureSchema);
|
||||
assert.isETHAddressHex('signerAddressHex', signerAddressHex);
|
||||
@@ -782,7 +882,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
);
|
||||
return isValidSignature;
|
||||
}
|
||||
private async _getOrderHashHexUsingContractCallAsync(order: Order|SignedOrder): Promise<string> {
|
||||
private async _getOrderHashHexUsingContractCallAsync(order: Order | SignedOrder): Promise<string> {
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
|
||||
const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues);
|
||||
@@ -793,7 +893,8 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
return this._exchangeContractIfExists;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.ExchangeArtifact, this._contractAddressIfExists,
|
||||
artifacts.ExchangeArtifact,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new ExchangeContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
||||
this._exchangeContractIfExists = contractInstance;
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import {Token, TokenMetadata} from '../types';
|
||||
import {assert} from '../utils/assert';
|
||||
import {constants} from '../utils/constants';
|
||||
import { artifacts } from '../artifacts';
|
||||
import { Token, TokenMetadata } from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {TokenRegistryContract} from './generated/token_registry';
|
||||
import { ContractWrapper } from './contract_wrapper';
|
||||
import { TokenRegistryContract } from './generated/token_registry';
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with the 0x Token Registry smart contract.
|
||||
@@ -15,7 +15,7 @@ import {TokenRegistryContract} from './generated/token_registry';
|
||||
export class TokenRegistryWrapper extends ContractWrapper {
|
||||
private _tokenRegistryContractIfExists?: TokenRegistryContract;
|
||||
private _contractAddressIfExists?: string;
|
||||
private static _createTokenFromMetadata(metadata: TokenMetadata): Token|undefined {
|
||||
private static _createTokenFromMetadata(metadata: TokenMetadata): Token | undefined {
|
||||
if (metadata[0] === constants.NULL_ADDRESS) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -37,9 +37,8 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
*/
|
||||
public async getTokensAsync(): Promise<Token[]> {
|
||||
const addresses = await this.getTokenAddressesAsync();
|
||||
const tokenPromises: Array<Promise<Token|undefined>> = _.map(
|
||||
addresses,
|
||||
async (address: string) => this.getTokenIfExistsAsync(address),
|
||||
const tokenPromises: Array<Promise<Token | undefined>> = _.map(addresses, async (address: string) =>
|
||||
this.getTokenIfExistsAsync(address),
|
||||
);
|
||||
const tokens = await Promise.all(tokenPromises);
|
||||
return tokens as Token[];
|
||||
@@ -57,7 +56,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
* Retrieves a token by address currently listed in the Token Registry smart contract
|
||||
* @return An object that conforms to the Token interface or undefined if token not found.
|
||||
*/
|
||||
public async getTokenIfExistsAsync(address: string): Promise<Token|undefined> {
|
||||
public async getTokenIfExistsAsync(address: string): Promise<Token | undefined> {
|
||||
assert.isETHAddressHex('address', address);
|
||||
|
||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||
@@ -65,7 +64,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
|
||||
return token;
|
||||
}
|
||||
public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string|undefined> {
|
||||
public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string | undefined> {
|
||||
assert.isString('symbol', symbol);
|
||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||
const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.callAsync(symbol);
|
||||
@@ -74,7 +73,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
}
|
||||
return addressIfExists;
|
||||
}
|
||||
public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string|undefined> {
|
||||
public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string | undefined> {
|
||||
assert.isString('name', name);
|
||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||
const addressIfExists = await tokenRegistryContract.getTokenAddressByName.callAsync(name);
|
||||
@@ -83,14 +82,14 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
}
|
||||
return addressIfExists;
|
||||
}
|
||||
public async getTokenBySymbolIfExistsAsync(symbol: string): Promise<Token|undefined> {
|
||||
public async getTokenBySymbolIfExistsAsync(symbol: string): Promise<Token | undefined> {
|
||||
assert.isString('symbol', symbol);
|
||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||
const metadata = await tokenRegistryContract.getTokenBySymbol.callAsync(symbol);
|
||||
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
|
||||
return token;
|
||||
}
|
||||
public async getTokenByNameIfExistsAsync(name: string): Promise<Token|undefined> {
|
||||
public async getTokenByNameIfExistsAsync(name: string): Promise<Token | undefined> {
|
||||
assert.isString('name', name);
|
||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||
const metadata = await tokenRegistryContract.getTokenByName.callAsync(name);
|
||||
@@ -104,7 +103,8 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
*/
|
||||
public getContractAddress(): string {
|
||||
const contractAddress = this._getContractAddress(
|
||||
artifacts.TokenRegistryArtifact, this._contractAddressIfExists,
|
||||
artifacts.TokenRegistryArtifact,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
return contractAddress;
|
||||
}
|
||||
@@ -116,10 +116,12 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
return this._tokenRegistryContractIfExists;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.TokenRegistryArtifact, this._contractAddressIfExists,
|
||||
artifacts.TokenRegistryArtifact,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new TokenRegistryContract(
|
||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
||||
web3ContractInstance,
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
this._tokenRegistryContractIfExists = contractInstance;
|
||||
return this._tokenRegistryContractIfExists;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import { artifacts } from '../artifacts';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {TokenTransferProxyContract} from './generated/token_transfer_proxy';
|
||||
import { ContractWrapper } from './contract_wrapper';
|
||||
import { TokenTransferProxyContract } from './generated/token_transfer_proxy';
|
||||
|
||||
/**
|
||||
* This class includes the functionality related to interacting with the TokenTransferProxy contract.
|
||||
@@ -42,7 +42,8 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
||||
*/
|
||||
public getContractAddress(): string {
|
||||
const contractAddress = this._getContractAddress(
|
||||
artifacts.TokenTransferProxyArtifact, this._contractAddressIfExists,
|
||||
artifacts.TokenTransferProxyArtifact,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
return contractAddress;
|
||||
}
|
||||
@@ -54,10 +55,12 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
||||
return this._tokenTransferProxyContractIfExists;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.TokenTransferProxyArtifact, this._contractAddressIfExists,
|
||||
artifacts.TokenTransferProxyArtifact,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new TokenTransferProxyContract(
|
||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
||||
web3ContractInstance,
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
this._tokenTransferProxyContractIfExists = contractInstance;
|
||||
return this._tokenTransferProxyContractIfExists;
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import { artifacts } from '../artifacts';
|
||||
import {
|
||||
BlockRange,
|
||||
EventCallback,
|
||||
@@ -15,13 +15,13 @@ import {
|
||||
TransactionOpts,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {assert} from '../utils/assert';
|
||||
import {constants} from '../utils/constants';
|
||||
import { AbiDecoder } from '../utils/abi_decoder';
|
||||
import { assert } from '../utils/assert';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {TokenContract} from './generated/token';
|
||||
import {TokenTransferProxyWrapper} from './token_transfer_proxy_wrapper';
|
||||
import { ContractWrapper } from './contract_wrapper';
|
||||
import { TokenContract } from './generated/token';
|
||||
import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper';
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with ERC20 token contracts.
|
||||
@@ -30,10 +30,14 @@ import {TokenTransferProxyWrapper} from './token_transfer_proxy_wrapper';
|
||||
*/
|
||||
export class TokenWrapper extends ContractWrapper {
|
||||
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
||||
private _tokenContractsByAddress: {[address: string]: TokenContract};
|
||||
private _tokenContractsByAddress: { [address: string]: TokenContract };
|
||||
private _tokenTransferProxyWrapper: TokenTransferProxyWrapper;
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder,
|
||||
tokenTransferProxyWrapper: TokenTransferProxyWrapper) {
|
||||
constructor(
|
||||
web3Wrapper: Web3Wrapper,
|
||||
networkId: number,
|
||||
abiDecoder: AbiDecoder,
|
||||
tokenTransferProxyWrapper: TokenTransferProxyWrapper,
|
||||
) {
|
||||
super(web3Wrapper, networkId, abiDecoder);
|
||||
this._tokenContractsByAddress = {};
|
||||
this._tokenTransferProxyWrapper = tokenTransferProxyWrapper;
|
||||
@@ -45,8 +49,11 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
* @return The owner's ERC20 token balance in base units.
|
||||
*/
|
||||
public async getBalanceAsync(tokenAddress: string, ownerAddress: string,
|
||||
methodOpts?: MethodOpts): Promise<BigNumber> {
|
||||
public async getBalanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
methodOpts?: MethodOpts,
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
|
||||
@@ -68,8 +75,13 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setAllowanceAsync(tokenAddress: string, ownerAddress: string, spenderAddress: string,
|
||||
amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}): Promise<string> {
|
||||
public async setAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
spenderAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
|
||||
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
@@ -95,10 +107,18 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setUnlimitedAllowanceAsync(tokenAddress: string, ownerAddress: string,
|
||||
spenderAddress: string, txOpts: TransactionOpts = {}): Promise<string> {
|
||||
public async setUnlimitedAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
spenderAddress: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
const txHash = await this.setAllowanceAsync(
|
||||
tokenAddress, ownerAddress, spenderAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, txOpts,
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
txOpts,
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
@@ -110,8 +130,12 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching.
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
*/
|
||||
public async getAllowanceAsync(tokenAddress: string, ownerAddress: string,
|
||||
spenderAddress: string, methodOpts?: MethodOpts): Promise<BigNumber> {
|
||||
public async getAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
spenderAddress: string,
|
||||
methodOpts?: MethodOpts,
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
|
||||
@@ -128,8 +152,11 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @param ownerAddress The hex encoded user Ethereum address whose proxy contract allowance we are retrieving.
|
||||
* @param methodOpts Optional arguments this method accepts.
|
||||
*/
|
||||
public async getProxyAllowanceAsync(tokenAddress: string, ownerAddress: string,
|
||||
methodOpts?: MethodOpts): Promise<BigNumber> {
|
||||
public async getProxyAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
methodOpts?: MethodOpts,
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
|
||||
@@ -147,15 +174,23 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setProxyAllowanceAsync(tokenAddress: string, ownerAddress: string,
|
||||
amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}): Promise<string> {
|
||||
public async setProxyAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||
|
||||
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
|
||||
const txHash = await this.setAllowanceAsync(
|
||||
tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits, txOpts,
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
proxyAddress,
|
||||
amountInBaseUnits,
|
||||
txOpts,
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
@@ -171,10 +206,15 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async setUnlimitedProxyAllowanceAsync(
|
||||
tokenAddress: string, ownerAddress: string, txOpts: TransactionOpts = {},
|
||||
tokenAddress: string,
|
||||
ownerAddress: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
const txHash = await this.setProxyAllowanceAsync(
|
||||
tokenAddress, ownerAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, txOpts,
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
txOpts,
|
||||
);
|
||||
return txHash;
|
||||
}
|
||||
@@ -187,8 +227,13 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async transferAsync(tokenAddress: string, fromAddress: string, toAddress: string,
|
||||
amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}): Promise<string> {
|
||||
public async transferAsync(
|
||||
tokenAddress: string,
|
||||
fromAddress: string,
|
||||
toAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
|
||||
assert.isETHAddressHex('toAddress', toAddress);
|
||||
@@ -222,9 +267,14 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async transferFromAsync(tokenAddress: string, fromAddress: string, toAddress: string,
|
||||
senderAddress: string, amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}):
|
||||
Promise<string> {
|
||||
public async transferFromAsync(
|
||||
tokenAddress: string,
|
||||
fromAddress: string,
|
||||
toAddress: string,
|
||||
senderAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('fromAddress', fromAddress);
|
||||
assert.isETHAddressHex('toAddress', toAddress);
|
||||
@@ -244,7 +294,9 @@ export class TokenWrapper extends ContractWrapper {
|
||||
}
|
||||
|
||||
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
|
||||
fromAddress, toAddress, amountInBaseUnits,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
amountInBaseUnits,
|
||||
{
|
||||
from: senderAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
@@ -263,14 +315,21 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @return Subscription token used later to unsubscribe
|
||||
*/
|
||||
public subscribe<ArgsType extends TokenContractEventArgs>(
|
||||
tokenAddress: string, eventName: TokenEvents, indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>): string {
|
||||
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<ArgsType>(
|
||||
tokenAddress, eventName, indexFilterValues, artifacts.TokenArtifact.abi, callback,
|
||||
tokenAddress,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
artifacts.TokenArtifact.abi,
|
||||
callback,
|
||||
);
|
||||
return subscriptionToken;
|
||||
}
|
||||
@@ -297,14 +356,21 @@ export class TokenWrapper extends ContractWrapper {
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
|
||||
tokenAddress: string, eventName: TokenEvents, blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
tokenAddress: string,
|
||||
eventName: TokenEvents,
|
||||
blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const logs = await this._getLogsAsync<ArgsType>(
|
||||
tokenAddress, eventName, blockRange, indexFilterValues, artifacts.TokenArtifact.abi,
|
||||
tokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
artifacts.TokenArtifact.abi,
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
@@ -318,11 +384,10 @@ export class TokenWrapper extends ContractWrapper {
|
||||
return tokenContract;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.TokenArtifact, tokenAddress,
|
||||
);
|
||||
const contractInstance = new TokenContract(
|
||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
||||
artifacts.TokenArtifact,
|
||||
tokenAddress,
|
||||
);
|
||||
const contractInstance = new TokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
||||
tokenContract = contractInstance;
|
||||
this._tokenContractsByAddress[tokenAddress] = tokenContract;
|
||||
return tokenContract;
|
||||
|
3
packages/0x.js/src/globals.d.ts
vendored
3
packages/0x.js/src/globals.d.ts
vendored
@@ -57,8 +57,7 @@ declare module 'truffle-hdwallet-provider' {
|
||||
}
|
||||
|
||||
// abi-decoder declarations
|
||||
interface DecodedLogArg {
|
||||
}
|
||||
interface DecodedLogArg {}
|
||||
interface DecodedLog {
|
||||
name: string;
|
||||
events: DecodedLogArg[];
|
||||
|
4
packages/0x.js/src/globalsAugment.d.ts
vendored
4
packages/0x.js/src/globalsAugment.d.ts
vendored
@@ -9,7 +9,7 @@ declare global {
|
||||
/* tslint:disable */
|
||||
namespace Chai {
|
||||
interface NumberComparer {
|
||||
(value: number|BigNumber, message?: string): Assertion;
|
||||
(value: number | BigNumber, message?: string): Assertion;
|
||||
}
|
||||
interface NumericComparison {
|
||||
greaterThan: NumberComparer;
|
||||
@@ -18,6 +18,6 @@ declare global {
|
||||
/* tslint:enable */
|
||||
interface DecodedLogArg {
|
||||
name: string;
|
||||
value: string|BigNumber;
|
||||
value: string | BigNumber;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
export {ZeroEx} from './0x';
|
||||
export { ZeroEx } from './0x';
|
||||
|
||||
export {
|
||||
Order,
|
||||
@@ -47,6 +47,4 @@ export {
|
||||
OrderState,
|
||||
} from './types';
|
||||
|
||||
export {
|
||||
TransactionReceipt,
|
||||
} from '@0xproject/types';
|
||||
export { TransactionReceipt } from '@0xproject/types';
|
||||
|
@@ -1,14 +1,10 @@
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { intervalUtils } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
EventWatcherCallback,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {assert} from '../utils/assert';
|
||||
import { BlockParamLiteral, EventWatcherCallback, ZeroExError } from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
|
||||
const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200;
|
||||
|
||||
@@ -26,11 +22,11 @@ export class EventWatcher {
|
||||
private _pollingIntervalMs: number;
|
||||
private _intervalIdIfExists?: NodeJS.Timer;
|
||||
private _lastEvents: Web3.LogEntry[] = [];
|
||||
constructor(web3Wrapper: Web3Wrapper, pollingIntervalIfExistsMs: undefined|number) {
|
||||
constructor(web3Wrapper: Web3Wrapper, pollingIntervalIfExistsMs: undefined | number) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs) ?
|
||||
DEFAULT_EVENT_POLLING_INTERVAL_MS :
|
||||
pollingIntervalIfExistsMs;
|
||||
this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs)
|
||||
? DEFAULT_EVENT_POLLING_INTERVAL_MS
|
||||
: pollingIntervalIfExistsMs;
|
||||
}
|
||||
public subscribe(callback: EventWatcherCallback): void {
|
||||
assert.isFunction('callback', callback);
|
||||
@@ -38,7 +34,8 @@ export class EventWatcher {
|
||||
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
|
||||
}
|
||||
this._intervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
||||
this._pollForBlockchainEventsAsync.bind(this, callback), this._pollingIntervalMs,
|
||||
this._pollForBlockchainEventsAsync.bind(this, callback),
|
||||
this._pollingIntervalMs,
|
||||
);
|
||||
}
|
||||
public unsubscribe(): void {
|
||||
@@ -71,7 +68,9 @@ export class EventWatcher {
|
||||
return events;
|
||||
}
|
||||
private async _emitDifferencesAsync(
|
||||
logs: Web3.LogEntry[], logEventState: LogEventState, callback: EventWatcherCallback,
|
||||
logs: Web3.LogEntry[],
|
||||
logEventState: LogEventState,
|
||||
callback: EventWatcherCallback,
|
||||
): Promise<void> {
|
||||
for (const log of logs) {
|
||||
const logEvent = {
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import {RBTree} from 'bintrees';
|
||||
import { intervalUtils } from '@0xproject/utils';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { RBTree } from 'bintrees';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ZeroExError} from '../types';
|
||||
import {utils} from '../utils/utils';
|
||||
import { ZeroExError } from '../types';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
const DEFAULT_EXPIRATION_MARGIN_MS = 0;
|
||||
const DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS = 50;
|
||||
@@ -15,16 +15,14 @@ const DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS = 50;
|
||||
*/
|
||||
export class ExpirationWatcher {
|
||||
private _orderHashByExpirationRBTree: RBTree<string>;
|
||||
private _expiration: {[orderHash: string]: BigNumber} = {};
|
||||
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;
|
||||
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);
|
||||
@@ -34,7 +32,8 @@ export class ExpirationWatcher {
|
||||
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
|
||||
}
|
||||
this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
||||
this._pruneExpiredOrders.bind(this, callback), this._orderExpirationCheckingIntervalMs,
|
||||
this._pruneExpiredOrders.bind(this, callback),
|
||||
this._orderExpirationCheckingIntervalMs,
|
||||
);
|
||||
}
|
||||
public unsubscribe(): void {
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { intervalUtils } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ZeroEx} from '../0x';
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
||||
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
|
||||
import {OrderFilledCancelledLazyStore} from '../stores/order_filled_cancelled_lazy_store';
|
||||
import { ZeroEx } from '../0x';
|
||||
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
||||
import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
|
||||
import {
|
||||
ApprovalContractEventArgs,
|
||||
BlockParamLiteral,
|
||||
@@ -29,13 +29,13 @@ import {
|
||||
WithdrawalContractEventArgs,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {assert} from '../utils/assert';
|
||||
import {OrderStateUtils} from '../utils/order_state_utils';
|
||||
import {utils} from '../utils/utils';
|
||||
import { AbiDecoder } from '../utils/abi_decoder';
|
||||
import { assert } from '../utils/assert';
|
||||
import { OrderStateUtils } from '../utils/order_state_utils';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import {EventWatcher} from './event_watcher';
|
||||
import {ExpirationWatcher} from './expiration_watcher';
|
||||
import { EventWatcher } from './event_watcher';
|
||||
import { ExpirationWatcher } from './expiration_watcher';
|
||||
|
||||
interface DependentOrderHashes {
|
||||
[makerAddress: string]: {
|
||||
@@ -74,7 +74,10 @@ export class OrderStateWatcher {
|
||||
private _cleanupJobInterval: number;
|
||||
private _cleanupJobIntervalIdIfExists?: NodeJS.Timer;
|
||||
constructor(
|
||||
web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder, token: TokenWrapper, exchange: ExchangeWrapper,
|
||||
web3Wrapper: Web3Wrapper,
|
||||
abiDecoder: AbiDecoder,
|
||||
token: TokenWrapper,
|
||||
exchange: ExchangeWrapper,
|
||||
config?: OrderStateWatcherConfig,
|
||||
) {
|
||||
this._abiDecoder = abiDecoder;
|
||||
@@ -82,24 +85,26 @@ export class OrderStateWatcher {
|
||||
const pollingIntervalIfExistsMs = _.isUndefined(config) ? undefined : config.eventPollingIntervalMs;
|
||||
this._eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalIfExistsMs);
|
||||
this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(
|
||||
token, BlockParamLiteral.Pending,
|
||||
token,
|
||||
BlockParamLiteral.Pending,
|
||||
);
|
||||
this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(exchange);
|
||||
this._orderStateUtils = new OrderStateUtils(
|
||||
this._balanceAndProxyAllowanceLazyStore, this._orderFilledCancelledLazyStore,
|
||||
this._balanceAndProxyAllowanceLazyStore,
|
||||
this._orderFilledCancelledLazyStore,
|
||||
);
|
||||
const orderExpirationCheckingIntervalMsIfExists = _.isUndefined(config) ?
|
||||
undefined :
|
||||
config.orderExpirationCheckingIntervalMs;
|
||||
const expirationMarginIfExistsMs = _.isUndefined(config) ?
|
||||
undefined :
|
||||
config.expirationMarginMs;
|
||||
const orderExpirationCheckingIntervalMsIfExists = _.isUndefined(config)
|
||||
? undefined
|
||||
: config.orderExpirationCheckingIntervalMs;
|
||||
const expirationMarginIfExistsMs = _.isUndefined(config) ? undefined : config.expirationMarginMs;
|
||||
this._expirationWatcher = new ExpirationWatcher(
|
||||
expirationMarginIfExistsMs, orderExpirationCheckingIntervalMsIfExists,
|
||||
expirationMarginIfExistsMs,
|
||||
orderExpirationCheckingIntervalMsIfExists,
|
||||
);
|
||||
this._cleanupJobInterval = _.isUndefined(config) || _.isUndefined(config.cleanupJobIntervalMs) ?
|
||||
DEFAULT_CLEANUP_JOB_INTERVAL_MS :
|
||||
config.cleanupJobIntervalMs;
|
||||
this._cleanupJobInterval =
|
||||
_.isUndefined(config) || _.isUndefined(config.cleanupJobIntervalMs)
|
||||
? DEFAULT_CLEANUP_JOB_INTERVAL_MS
|
||||
: config.cleanupJobIntervalMs;
|
||||
}
|
||||
/**
|
||||
* Add an order to the orderStateWatcher. Before the order is added, it's
|
||||
@@ -148,7 +153,8 @@ export class OrderStateWatcher {
|
||||
this._eventWatcher.subscribe(this._onEventWatcherCallbackAsync.bind(this));
|
||||
this._expirationWatcher.subscribe(this._onOrderExpired.bind(this));
|
||||
this._cleanupJobIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
||||
this._cleanupAsync.bind(this), this._cleanupJobInterval,
|
||||
this._cleanupAsync.bind(this),
|
||||
this._cleanupJobInterval,
|
||||
);
|
||||
}
|
||||
/**
|
||||
@@ -215,23 +221,23 @@ export class OrderStateWatcher {
|
||||
let makerToken: string;
|
||||
let makerAddress: string;
|
||||
switch (decodedLog.event) {
|
||||
case TokenEvents.Approval:
|
||||
{
|
||||
case TokenEvents.Approval: {
|
||||
// Invalidate cache
|
||||
const args = decodedLog.args as ApprovalContractEventArgs;
|
||||
this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(decodedLog.address, args._owner);
|
||||
// Revalidate orders
|
||||
makerToken = decodedLog.address;
|
||||
makerAddress = args._owner;
|
||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
||||
if (
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
|
||||
) {
|
||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TokenEvents.Transfer:
|
||||
{
|
||||
case TokenEvents.Transfer: {
|
||||
// Invalidate cache
|
||||
const args = decodedLog.args as TransferContractEventArgs;
|
||||
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._from);
|
||||
@@ -239,45 +245,48 @@ export class OrderStateWatcher {
|
||||
// Revalidate orders
|
||||
makerToken = decodedLog.address;
|
||||
makerAddress = args._from;
|
||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
||||
if (
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
|
||||
) {
|
||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EtherTokenEvents.Deposit:
|
||||
{
|
||||
case EtherTokenEvents.Deposit: {
|
||||
// Invalidate cache
|
||||
const args = decodedLog.args as DepositContractEventArgs;
|
||||
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
|
||||
// Revalidate orders
|
||||
makerToken = decodedLog.address;
|
||||
makerAddress = args._owner;
|
||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
||||
if (
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
|
||||
) {
|
||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EtherTokenEvents.Withdrawal:
|
||||
{
|
||||
case EtherTokenEvents.Withdrawal: {
|
||||
// Invalidate cache
|
||||
const args = decodedLog.args as WithdrawalContractEventArgs;
|
||||
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
|
||||
// Revalidate orders
|
||||
makerToken = decodedLog.address;
|
||||
makerAddress = args._owner;
|
||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
||||
if (
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
|
||||
) {
|
||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExchangeEvents.LogFill:
|
||||
{
|
||||
case ExchangeEvents.LogFill: {
|
||||
// Invalidate cache
|
||||
const args = decodedLog.args as LogFillContractEventArgs;
|
||||
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(args.orderHash);
|
||||
@@ -289,8 +298,7 @@ export class OrderStateWatcher {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExchangeEvents.LogCancel:
|
||||
{
|
||||
case ExchangeEvents.LogCancel: {
|
||||
// Invalidate cache
|
||||
const args = decodedLog.args as LogCancelContractEventArgs;
|
||||
this._orderFilledCancelledLazyStore.deleteCancelledTakerAmount(args.orderHash);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
|
||||
import {SignedOrder} from '../types';
|
||||
import { SignedOrder } from '../types';
|
||||
|
||||
export class RemainingFillableCalculator {
|
||||
private _signedOrder: SignedOrder;
|
||||
@@ -10,18 +10,21 @@ export class RemainingFillableCalculator {
|
||||
private _transferrableMakerFeeTokenAmount: BigNumber;
|
||||
private _remainingMakerTokenAmount: BigNumber;
|
||||
private _remainingMakerFeeAmount: BigNumber;
|
||||
constructor(signedOrder: SignedOrder,
|
||||
isMakerTokenZRX: boolean,
|
||||
transferrableMakerTokenAmount: BigNumber,
|
||||
transferrableMakerFeeTokenAmount: BigNumber,
|
||||
remainingMakerTokenAmount: BigNumber) {
|
||||
constructor(
|
||||
signedOrder: SignedOrder,
|
||||
isMakerTokenZRX: boolean,
|
||||
transferrableMakerTokenAmount: BigNumber,
|
||||
transferrableMakerFeeTokenAmount: BigNumber,
|
||||
remainingMakerTokenAmount: BigNumber,
|
||||
) {
|
||||
this._signedOrder = signedOrder;
|
||||
this._isMakerTokenZRX = isMakerTokenZRX;
|
||||
this._transferrableMakerTokenAmount = transferrableMakerTokenAmount;
|
||||
this._transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount;
|
||||
this._remainingMakerTokenAmount = remainingMakerTokenAmount;
|
||||
this._remainingMakerFeeAmount = remainingMakerTokenAmount.times(signedOrder.makerFee)
|
||||
.dividedToIntegerBy(signedOrder.makerTokenAmount);
|
||||
this._remainingMakerFeeAmount = remainingMakerTokenAmount
|
||||
.times(signedOrder.makerFee)
|
||||
.dividedToIntegerBy(signedOrder.makerTokenAmount);
|
||||
}
|
||||
public computeRemainingMakerFillable(): BigNumber {
|
||||
if (this._hasSufficientFundsForFeeAndTransferAmount()) {
|
||||
@@ -33,20 +36,24 @@ export class RemainingFillableCalculator {
|
||||
return this._calculatePartiallyFillableMakerTokenAmount();
|
||||
}
|
||||
public computeRemainingTakerFillable(): BigNumber {
|
||||
return this.computeRemainingMakerFillable().times(this._signedOrder.takerTokenAmount)
|
||||
.dividedToIntegerBy(this._signedOrder.makerTokenAmount);
|
||||
return this.computeRemainingMakerFillable()
|
||||
.times(this._signedOrder.takerTokenAmount)
|
||||
.dividedToIntegerBy(this._signedOrder.makerTokenAmount);
|
||||
}
|
||||
private _hasSufficientFundsForFeeAndTransferAmount(): boolean {
|
||||
if (this._isMakerTokenZRX) {
|
||||
const totalZRXTransferAmountRequired = this._remainingMakerTokenAmount.plus(this._remainingMakerFeeAmount);
|
||||
const hasSufficientFunds = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
|
||||
totalZRXTransferAmountRequired);
|
||||
totalZRXTransferAmountRequired,
|
||||
);
|
||||
return hasSufficientFunds;
|
||||
} else {
|
||||
const hasSufficientFundsForTransferAmount = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
|
||||
this._remainingMakerTokenAmount);
|
||||
this._remainingMakerTokenAmount,
|
||||
);
|
||||
const hasSufficientFundsForFeeAmount = this._transferrableMakerFeeTokenAmount.greaterThanOrEqualTo(
|
||||
this._remainingMakerFeeAmount);
|
||||
this._remainingMakerFeeAmount,
|
||||
);
|
||||
const hasSufficientFunds = hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount;
|
||||
return hasSufficientFunds;
|
||||
}
|
||||
@@ -57,8 +64,10 @@ export class RemainingFillableCalculator {
|
||||
// The number of times the maker can fill the order, if each fill only required the transfer of a single
|
||||
// baseUnit of fee tokens.
|
||||
// Given 2 ZRXwei, the maximum amount of times Maker can fill this order, in terms of fees, is 2
|
||||
const fillableTimesInFeeTokenBaseUnits = BigNumber.min(this._transferrableMakerFeeTokenAmount,
|
||||
this._remainingMakerFeeAmount);
|
||||
const fillableTimesInFeeTokenBaseUnits = BigNumber.min(
|
||||
this._transferrableMakerFeeTokenAmount,
|
||||
this._remainingMakerFeeAmount,
|
||||
);
|
||||
// The number of times the Maker can fill the order, given the Maker Token Balance
|
||||
// Assuming a balance of 150 wei, and an orderToFeeRatio of 100:1, maker can fill this order 1 time.
|
||||
let fillableTimesInMakerTokenUnits = this._transferrableMakerTokenAmount.dividedBy(orderToFeeRatio);
|
||||
@@ -68,20 +77,20 @@ export class RemainingFillableCalculator {
|
||||
const totalZRXTokenPooled = this._transferrableMakerTokenAmount;
|
||||
// The purchasing power here is less as the tokens are taken from the same Pool
|
||||
// For every one number of fills, we have to take an extra ZRX out of the pool
|
||||
fillableTimesInMakerTokenUnits = totalZRXTokenPooled.dividedBy(
|
||||
orderToFeeRatio.plus(new BigNumber(1)));
|
||||
|
||||
fillableTimesInMakerTokenUnits = totalZRXTokenPooled.dividedBy(orderToFeeRatio.plus(new BigNumber(1)));
|
||||
}
|
||||
// When Ratio is not fully divisible there can be remainders which cannot be represented, so they are floored.
|
||||
// This can result in a RoundingError being thrown by the Exchange Contract.
|
||||
const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits
|
||||
.times(this._signedOrder.makerTokenAmount)
|
||||
.dividedToIntegerBy(this._signedOrder.makerFee);
|
||||
.times(this._signedOrder.makerTokenAmount)
|
||||
.dividedToIntegerBy(this._signedOrder.makerFee);
|
||||
const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenBaseUnits
|
||||
.times(this._signedOrder.makerTokenAmount)
|
||||
.dividedToIntegerBy(this._signedOrder.makerFee);
|
||||
const partiallyFillableAmount = BigNumber.min(partiallyFillableMakerTokenAmount,
|
||||
partiallyFillableFeeTokenAmount);
|
||||
.times(this._signedOrder.makerTokenAmount)
|
||||
.dividedToIntegerBy(this._signedOrder.makerFee);
|
||||
const partiallyFillableAmount = BigNumber.min(
|
||||
partiallyFillableMakerTokenAmount,
|
||||
partiallyFillableFeeTokenAmount,
|
||||
);
|
||||
return partiallyFillableAmount;
|
||||
}
|
||||
}
|
||||
|
@@ -5,9 +5,9 @@ export const zeroExConfigSchema = {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
gasPrice: {$ref: '/Number'},
|
||||
exchangeContractAddress: {$ref: '/Address'},
|
||||
tokenRegistryContractAddress: {$ref: '/Address'},
|
||||
gasPrice: { $ref: '/Number' },
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
tokenRegistryContractAddress: { $ref: '/Address' },
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
||||
import {BlockParamLiteral} from '../types';
|
||||
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||
import { BlockParamLiteral } from '../types';
|
||||
|
||||
/**
|
||||
* Copy on read store for balances/proxyAllowances of tokens/accounts
|
||||
@@ -52,8 +52,10 @@ export class BalanceAndProxyAllowanceLazyStore {
|
||||
}
|
||||
}
|
||||
public async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
|
||||
if (_.isUndefined(this._proxyAllowance[tokenAddress]) ||
|
||||
_.isUndefined(this._proxyAllowance[tokenAddress][userAddress])) {
|
||||
if (
|
||||
_.isUndefined(this._proxyAllowance[tokenAddress]) ||
|
||||
_.isUndefined(this._proxyAllowance[tokenAddress][userAddress])
|
||||
) {
|
||||
const methodOpts = {
|
||||
defaultBlock: this._defaultBlock,
|
||||
};
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {BlockParamLiteral} from '../types';
|
||||
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||
import { BlockParamLiteral } from '../types';
|
||||
|
||||
/**
|
||||
* Copy on read store for filled/cancelled taker amounts
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {TransactionReceipt} from '@0xproject/types';
|
||||
import { TransactionReceipt } from '@0xproject/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
@@ -42,8 +42,7 @@ export interface ECSignature {
|
||||
|
||||
export type OrderAddresses = [string, string, string, string, string];
|
||||
|
||||
export type OrderValues = [BigNumber, BigNumber, BigNumber,
|
||||
BigNumber, BigNumber, BigNumber];
|
||||
export type OrderValues = [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber, BigNumber];
|
||||
|
||||
export type LogEvent = Web3.LogEntryEvent;
|
||||
export interface DecodedLogEvent<ArgsType> {
|
||||
@@ -51,7 +50,7 @@ export interface DecodedLogEvent<ArgsType> {
|
||||
log: LogWithDecodedArgs<ArgsType>;
|
||||
}
|
||||
|
||||
export type EventCallback<ArgsType> = (err: null|Error, log?: DecodedLogEvent<ArgsType>) => void;
|
||||
export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void;
|
||||
export type EventWatcherCallback = (log: LogEvent) => void;
|
||||
|
||||
export enum SolidityTypes {
|
||||
@@ -136,7 +135,10 @@ export interface LogErrorContractEventArgs {
|
||||
errorId: BigNumber;
|
||||
orderHash: string;
|
||||
}
|
||||
export type ExchangeContractEventArgs = LogFillContractEventArgs|LogCancelContractEventArgs|LogErrorContractEventArgs;
|
||||
export type ExchangeContractEventArgs =
|
||||
| LogFillContractEventArgs
|
||||
| LogCancelContractEventArgs
|
||||
| LogErrorContractEventArgs;
|
||||
export interface TransferContractEventArgs {
|
||||
_from: string;
|
||||
_to: string;
|
||||
@@ -155,10 +157,13 @@ export interface WithdrawalContractEventArgs {
|
||||
_owner: string;
|
||||
_value: BigNumber;
|
||||
}
|
||||
export type TokenContractEventArgs = TransferContractEventArgs|ApprovalContractEventArgs;
|
||||
export type EtherTokenContractEventArgs = TokenContractEventArgs|DepositContractEventArgs|WithdrawalContractEventArgs;
|
||||
export type ContractEventArgs = ExchangeContractEventArgs|TokenContractEventArgs|EtherTokenContractEventArgs;
|
||||
export type ContractEventArg = string|BigNumber;
|
||||
export type TokenContractEventArgs = TransferContractEventArgs | ApprovalContractEventArgs;
|
||||
export type EtherTokenContractEventArgs =
|
||||
| TokenContractEventArgs
|
||||
| DepositContractEventArgs
|
||||
| WithdrawalContractEventArgs;
|
||||
export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs;
|
||||
export type ContractEventArg = string | BigNumber;
|
||||
|
||||
export interface Order {
|
||||
maker: string;
|
||||
@@ -211,14 +216,14 @@ export enum TokenEvents {
|
||||
Approval = 'Approval',
|
||||
}
|
||||
|
||||
export enum EtherTokenEvents {
|
||||
export enum EtherTokenEvents {
|
||||
Transfer = 'Transfer',
|
||||
Approval = 'Approval',
|
||||
Deposit = 'Deposit',
|
||||
Withdrawal = 'Withdrawal',
|
||||
}
|
||||
|
||||
export type ContractEvents = TokenEvents|ExchangeEvents|EtherTokenEvents;
|
||||
export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents;
|
||||
|
||||
export interface IndexedFilterValues {
|
||||
[index: string]: ContractEventArg;
|
||||
@@ -232,7 +237,7 @@ export enum BlockParamLiteral {
|
||||
Pending = 'pending',
|
||||
}
|
||||
|
||||
export type BlockParam = BlockParamLiteral|number;
|
||||
export type BlockParam = BlockParamLiteral | number;
|
||||
|
||||
export interface BlockRange {
|
||||
fromBlock: BlockParam;
|
||||
@@ -242,7 +247,7 @@ export interface BlockRange {
|
||||
export type DoneCallback = (err?: Error) => void;
|
||||
|
||||
export interface OrderCancellationRequest {
|
||||
order: Order|SignedOrder;
|
||||
order: Order | SignedOrder;
|
||||
takerTokenCancelAmount: BigNumber;
|
||||
}
|
||||
|
||||
@@ -312,10 +317,10 @@ export interface DecodedLogArgs {
|
||||
export interface LogWithDecodedArgs<ArgsType> extends Web3.DecodedLogEntry<ArgsType> {}
|
||||
|
||||
export interface TransactionReceiptWithDecodedLogs extends TransactionReceipt {
|
||||
logs: Array<LogWithDecodedArgs<DecodedLogArgs>|Web3.LogEntry>;
|
||||
logs: Array<LogWithDecodedArgs<DecodedLogArgs> | Web3.LogEntry>;
|
||||
}
|
||||
|
||||
export type ArtifactContractName = 'ZRX'|'TokenTransferProxy'|'TokenRegistry'|'Token'|'Exchange'|'EtherToken';
|
||||
export type ArtifactContractName = 'ZRX' | 'TokenTransferProxy' | 'TokenRegistry' | 'Token' | 'Exchange' | 'EtherToken';
|
||||
|
||||
export interface Artifact {
|
||||
contract_name: ArtifactContractName;
|
||||
@@ -399,7 +404,7 @@ export interface OrderStateInvalid {
|
||||
error: ExchangeContractErrs;
|
||||
}
|
||||
|
||||
export type OrderState = OrderStateValid|OrderStateInvalid;
|
||||
export type OrderState = OrderStateValid | OrderStateInvalid;
|
||||
|
||||
export type OnOrderStateChangeCallback = (orderState: OrderState) => void;
|
||||
// tslint:disable:max-file-line-count
|
||||
|
@@ -3,11 +3,11 @@ import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
import * as SolidityCoder from 'web3/lib/solidity/coder';
|
||||
|
||||
import {AbiType, ContractEventArgs, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes} from '../types';
|
||||
import { AbiType, ContractEventArgs, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes } from '../types';
|
||||
|
||||
export class AbiDecoder {
|
||||
private _savedABIs: Web3.AbiDefinition[] = [];
|
||||
private _methodIds: {[signatureHash: string]: Web3.EventAbi} = {};
|
||||
private _methodIds: { [signatureHash: string]: Web3.EventAbi } = {};
|
||||
private static _padZeros(address: string) {
|
||||
let formatted = address;
|
||||
if (_.startsWith(formatted, '0x')) {
|
||||
@@ -22,7 +22,8 @@ export class AbiDecoder {
|
||||
}
|
||||
// This method can only decode logs from the 0x & ERC20 smart contracts
|
||||
public tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
|
||||
log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog {
|
||||
log: Web3.LogEntry,
|
||||
): LogWithDecodedArgs<ArgsType> | RawLog {
|
||||
const methodId = log.topics[0];
|
||||
const event = this._methodIds[methodId];
|
||||
if (_.isUndefined(event)) {
|
||||
@@ -42,9 +43,11 @@ export class AbiDecoder {
|
||||
let value = param.indexed ? log.topics[topicsIndex++] : decodedData[dataIndex++];
|
||||
if (param.type === SolidityTypes.Address) {
|
||||
value = AbiDecoder._padZeros(new BigNumber(value).toString(16));
|
||||
} else if (param.type === SolidityTypes.Uint256 ||
|
||||
param.type === SolidityTypes.Uint8 ||
|
||||
param.type === SolidityTypes.Uint) {
|
||||
} else if (
|
||||
param.type === SolidityTypes.Uint256 ||
|
||||
param.type === SolidityTypes.Uint8 ||
|
||||
param.type === SolidityTypes.Uint
|
||||
) {
|
||||
value = new BigNumber(value);
|
||||
}
|
||||
decodedParams[param.name] = value;
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import {assert as sharedAssert} from '@0xproject/assert';
|
||||
import { assert as sharedAssert } from '@0xproject/assert';
|
||||
// We need those two unused imports because they're actually used by sharedAssert which gets injected here
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import {Schema} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { Schema } from '@0xproject/json-schemas';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import * as BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ECSignature} from '../types';
|
||||
import {signatureUtils} from '../utils/signature_utils';
|
||||
import { ECSignature } from '../types';
|
||||
import { signatureUtils } from '../utils/signature_utils';
|
||||
|
||||
export const assert = {
|
||||
...sharedAssert,
|
||||
@@ -16,11 +16,15 @@ export const assert = {
|
||||
const isValidSignature = signatureUtils.isValidSignature(orderHash, ecSignature, signerAddress);
|
||||
this.assert(isValidSignature, `Expected order with hash '${orderHash}' to have a valid signature`);
|
||||
},
|
||||
async isSenderAddressAsync(variableName: string, senderAddressHex: string,
|
||||
web3Wrapper: Web3Wrapper): Promise<void> {
|
||||
async isSenderAddressAsync(
|
||||
variableName: string,
|
||||
senderAddressHex: string,
|
||||
web3Wrapper: Web3Wrapper,
|
||||
): Promise<void> {
|
||||
sharedAssert.isETHAddressHex(variableName, senderAddressHex);
|
||||
const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex);
|
||||
sharedAssert.assert(isSenderAddressAvailable,
|
||||
sharedAssert.assert(
|
||||
isSenderAddressAvailable,
|
||||
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
},
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {AsyncMethod, SyncMethod, ZeroExError} from '../types';
|
||||
import { AsyncMethod, SyncMethod, ZeroExError } from '../types';
|
||||
|
||||
import {constants} from './constants';
|
||||
import { constants } from './constants';
|
||||
|
||||
type ErrorTransformer = (err: Error) => Error;
|
||||
|
||||
@@ -19,7 +19,8 @@ const contractCallErrorTransformer = (error: Error) => {
|
||||
const schemaErrorTransformer = (error: Error) => {
|
||||
if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
const errMsg = 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
const errMsg =
|
||||
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
return new Error(errMsg);
|
||||
}
|
||||
return error;
|
||||
@@ -30,14 +31,16 @@ const schemaErrorTransformer = (error: Error) => {
|
||||
*/
|
||||
const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
||||
const asyncErrorHandlingDecorator = (
|
||||
target: object, key: string|symbol, descriptor: TypedPropertyDescriptor<AsyncMethod>,
|
||||
target: object,
|
||||
key: string | symbol,
|
||||
descriptor: TypedPropertyDescriptor<AsyncMethod>,
|
||||
) => {
|
||||
const originalMethod = (descriptor.value as AsyncMethod);
|
||||
const originalMethod = descriptor.value as AsyncMethod;
|
||||
|
||||
// Do not use arrow syntax here. Use a function expression in
|
||||
// order to use the correct value of `this` in this method
|
||||
// tslint:disable-next-line:only-arrow-functions
|
||||
descriptor.value = async function(...args: any[]) {
|
||||
descriptor.value = async function(...args: any[]) {
|
||||
try {
|
||||
const result = await originalMethod.apply(this, args);
|
||||
return result;
|
||||
@@ -55,9 +58,11 @@ const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
||||
|
||||
const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
||||
const syncErrorHandlingDecorator = (
|
||||
target: object, key: string|symbol, descriptor: TypedPropertyDescriptor<SyncMethod>,
|
||||
target: object,
|
||||
key: string | symbol,
|
||||
descriptor: TypedPropertyDescriptor<SyncMethod>,
|
||||
) => {
|
||||
const originalMethod = (descriptor.value as SyncMethod);
|
||||
const originalMethod = descriptor.value as SyncMethod;
|
||||
|
||||
// Do not use arrow syntax here. Use a function expression in
|
||||
// order to use the correct value of `this` in this method
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
||||
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
|
||||
import {BlockParamLiteral, ExchangeContractErrs, TradeSide, TransferType} from '../types';
|
||||
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
||||
import { BlockParamLiteral, ExchangeContractErrs, TradeSide, TransferType } from '../types';
|
||||
|
||||
enum FailureReason {
|
||||
Balance = 'balance',
|
||||
@@ -36,8 +36,11 @@ const ERR_MSG_MAPPING = {
|
||||
export class ExchangeTransferSimulator {
|
||||
private _store: BalanceAndProxyAllowanceLazyStore;
|
||||
private _UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
|
||||
private static _throwValidationError(failureReason: FailureReason, tradeSide: TradeSide,
|
||||
transferType: TransferType): never {
|
||||
private static _throwValidationError(
|
||||
failureReason: FailureReason,
|
||||
tradeSide: TradeSide,
|
||||
transferType: TransferType,
|
||||
): never {
|
||||
const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType];
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
@@ -54,9 +57,14 @@ export class ExchangeTransferSimulator {
|
||||
* @param tradeSide Is Maker/Taker transferring
|
||||
* @param transferType Is it a fee payment or a value transfer
|
||||
*/
|
||||
public async transferFromAsync(tokenAddress: string, from: string, to: string,
|
||||
amountInBaseUnits: BigNumber, tradeSide: TradeSide,
|
||||
transferType: TransferType): Promise<void> {
|
||||
public async transferFromAsync(
|
||||
tokenAddress: string,
|
||||
from: string,
|
||||
to: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
tradeSide: TradeSide,
|
||||
transferType: TransferType,
|
||||
): Promise<void> {
|
||||
const balance = await this._store.getBalanceAsync(tokenAddress, from);
|
||||
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from);
|
||||
if (proxyAllowance.lessThan(amountInBaseUnits)) {
|
||||
@@ -69,20 +77,29 @@ export class ExchangeTransferSimulator {
|
||||
await this._decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits);
|
||||
await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
|
||||
}
|
||||
private async _decreaseProxyAllowanceAsync(tokenAddress: string, userAddress: string,
|
||||
amountInBaseUnits: BigNumber): Promise<void> {
|
||||
private async _decreaseProxyAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
userAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
): Promise<void> {
|
||||
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress);
|
||||
if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
|
||||
this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits));
|
||||
}
|
||||
}
|
||||
private async _increaseBalanceAsync(tokenAddress: string, userAddress: string,
|
||||
amountInBaseUnits: BigNumber): Promise<void> {
|
||||
private async _increaseBalanceAsync(
|
||||
tokenAddress: string,
|
||||
userAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
): Promise<void> {
|
||||
const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
|
||||
this._store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits));
|
||||
}
|
||||
private async _decreaseBalanceAsync(tokenAddress: string, userAddress: string,
|
||||
amountInBaseUnits: BigNumber): Promise<void> {
|
||||
private async _decreaseBalanceAsync(
|
||||
tokenAddress: string,
|
||||
userAddress: string,
|
||||
amountInBaseUnits: BigNumber,
|
||||
): Promise<void> {
|
||||
const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
|
||||
this._store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits));
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import * as _ from 'lodash';
|
||||
import * as uuid from 'uuid/v4';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {BlockRange, ContractEvents, IndexedFilterValues} from '../types';
|
||||
import { BlockRange, ContractEvents, IndexedFilterValues } from '../types';
|
||||
|
||||
const TOPIC_LENGTH = 32;
|
||||
|
||||
@@ -12,10 +12,14 @@ export const filterUtils = {
|
||||
generateUUID(): string {
|
||||
return uuid();
|
||||
},
|
||||
getFilter(address: string, eventName: ContractEvents,
|
||||
indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi,
|
||||
blockRange?: BlockRange): Web3.FilterObject {
|
||||
const eventAbi = _.find(abi, {name: eventName}) as Web3.EventAbi;
|
||||
getFilter(
|
||||
address: string,
|
||||
eventName: ContractEvents,
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
abi: Web3.ContractAbi,
|
||||
blockRange?: BlockRange,
|
||||
): Web3.FilterObject {
|
||||
const eventAbi = _.find(abi, { name: eventName }) as Web3.EventAbi;
|
||||
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi, eventName);
|
||||
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
|
||||
const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
|
||||
@@ -37,8 +41,8 @@ export const filterUtils = {
|
||||
const signature = `${eventAbi.name}(${types.join(',')})`;
|
||||
return signature;
|
||||
},
|
||||
getTopicsForIndexedArgs(abi: Web3.EventAbi, indexFilterValues: IndexedFilterValues): Array<string|null> {
|
||||
const topics: Array<string|null> = [];
|
||||
getTopicsForIndexedArgs(abi: Web3.EventAbi, indexFilterValues: IndexedFilterValues): Array<string | null> {
|
||||
const topics: Array<string | null> = [];
|
||||
for (const eventInput of abi.inputs) {
|
||||
if (!eventInput.indexed) {
|
||||
continue;
|
||||
@@ -65,12 +69,12 @@ export const filterUtils = {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
matchesTopics(logTopics: string[], filterTopics: Array<string[]|string|null>): boolean {
|
||||
matchesTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean {
|
||||
const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils));
|
||||
const matchesTopics = _.every(matchesTopic);
|
||||
return matchesTopics;
|
||||
},
|
||||
matchesTopic(logTopic: string, filterTopic: string[]|string|null): boolean {
|
||||
matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean {
|
||||
if (_.isArray(filterTopic)) {
|
||||
return _.includes(filterTopic, logTopic);
|
||||
}
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ZeroEx} from '../0x';
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {RemainingFillableCalculator} from '../order_watcher/remaining_fillable_calculator';
|
||||
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
|
||||
import {OrderFilledCancelledLazyStore} from '../stores/order_filled_cancelled_lazy_store';
|
||||
import { ZeroEx } from '../0x';
|
||||
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||
import { RemainingFillableCalculator } from '../order_watcher/remaining_fillable_calculator';
|
||||
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
||||
import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
|
||||
import {
|
||||
ExchangeContractErrs,
|
||||
OrderRelevantState,
|
||||
@@ -44,15 +44,20 @@ export class OrderStateUtils {
|
||||
}
|
||||
}
|
||||
const minFillableTakerTokenAmountWithinNoRoundingErrorRange = signedOrder.takerTokenAmount
|
||||
.dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
|
||||
.dividedBy(signedOrder.makerTokenAmount);
|
||||
if (orderRelevantState.remainingFillableTakerTokenAmount
|
||||
.lessThan(minFillableTakerTokenAmountWithinNoRoundingErrorRange)) {
|
||||
.dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
|
||||
.dividedBy(signedOrder.makerTokenAmount);
|
||||
if (
|
||||
orderRelevantState.remainingFillableTakerTokenAmount.lessThan(
|
||||
minFillableTakerTokenAmountWithinNoRoundingErrorRange,
|
||||
)
|
||||
) {
|
||||
throw new Error(ExchangeContractErrs.OrderFillRoundingError);
|
||||
}
|
||||
}
|
||||
constructor(balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore,
|
||||
orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore) {
|
||||
constructor(
|
||||
balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore,
|
||||
orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore,
|
||||
) {
|
||||
this._balanceAndProxyAllowanceLazyStore = balanceAndProxyAllowanceLazyStore;
|
||||
this._orderFilledCancelledLazyStore = orderFilledCancelledLazyStore;
|
||||
}
|
||||
@@ -85,16 +90,20 @@ export class OrderStateUtils {
|
||||
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
const makerBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
|
||||
signedOrder.makerTokenAddress, signedOrder.maker,
|
||||
signedOrder.makerTokenAddress,
|
||||
signedOrder.maker,
|
||||
);
|
||||
const makerProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
|
||||
signedOrder.makerTokenAddress, signedOrder.maker,
|
||||
signedOrder.makerTokenAddress,
|
||||
signedOrder.maker,
|
||||
);
|
||||
const makerFeeBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
|
||||
zrxTokenAddress, signedOrder.maker,
|
||||
zrxTokenAddress,
|
||||
signedOrder.maker,
|
||||
);
|
||||
const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
|
||||
zrxTokenAddress, signedOrder.maker,
|
||||
zrxTokenAddress,
|
||||
signedOrder.maker,
|
||||
);
|
||||
const filledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getFilledTakerAmountAsync(orderHash);
|
||||
const cancelledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getCancelledTakerAmountAsync(
|
||||
@@ -104,17 +113,20 @@ export class OrderStateUtils {
|
||||
const totalMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||
const totalTakerTokenAmount = signedOrder.takerTokenAmount;
|
||||
const remainingTakerTokenAmount = totalTakerTokenAmount.minus(unavailableTakerTokenAmount);
|
||||
const remainingMakerTokenAmount = remainingTakerTokenAmount.times(totalMakerTokenAmount)
|
||||
.dividedToIntegerBy(totalTakerTokenAmount);
|
||||
const remainingMakerTokenAmount = remainingTakerTokenAmount
|
||||
.times(totalMakerTokenAmount)
|
||||
.dividedToIntegerBy(totalTakerTokenAmount);
|
||||
const transferrableMakerTokenAmount = BigNumber.min([makerProxyAllowance, makerBalance]);
|
||||
const transferrableFeeTokenAmount = BigNumber.min([makerFeeProxyAllowance, makerFeeBalance]);
|
||||
|
||||
const isMakerTokenZRX = signedOrder.makerTokenAddress === zrxTokenAddress;
|
||||
const remainingFillableCalculator = new RemainingFillableCalculator(signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableFeeTokenAmount,
|
||||
remainingMakerTokenAmount);
|
||||
const remainingFillableCalculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
const remainingFillableMakerTokenAmount = remainingFillableCalculator.computeRemainingMakerFillable();
|
||||
const remainingFillableTakerTokenAmount = remainingFillableCalculator.computeRemainingTakerFillable();
|
||||
const orderRelevantState = {
|
||||
|
@@ -1,18 +1,20 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ZeroEx} from '../0x';
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {ExchangeContractErrs, Order, SignedOrder, TradeSide, TransferType, ZeroExError} from '../types';
|
||||
import {constants} from '../utils/constants';
|
||||
import {utils} from '../utils/utils';
|
||||
import { ZeroEx } from '../0x';
|
||||
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||
import { ExchangeContractErrs, Order, SignedOrder, TradeSide, TransferType, ZeroExError } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import {ExchangeTransferSimulator} from './exchange_transfer_simulator';
|
||||
import { ExchangeTransferSimulator } from './exchange_transfer_simulator';
|
||||
|
||||
export class OrderValidationUtils {
|
||||
private _exchangeWrapper: ExchangeWrapper;
|
||||
public static validateCancelOrderThrowIfInvalid(
|
||||
order: Order, cancelTakerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
|
||||
order: Order,
|
||||
cancelTakerTokenAmount: BigNumber,
|
||||
unavailableTakerTokenAmount: BigNumber,
|
||||
): void {
|
||||
if (cancelTakerTokenAmount.eq(0)) {
|
||||
throw new Error(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
@@ -26,8 +28,11 @@ export class OrderValidationUtils {
|
||||
}
|
||||
}
|
||||
public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber, senderAddress: string, zrxTokenAddress: string,
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
senderAddress: string,
|
||||
zrxTokenAddress: string,
|
||||
): Promise<void> {
|
||||
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
|
||||
fillTakerTokenAmount,
|
||||
@@ -35,12 +40,20 @@ export class OrderValidationUtils {
|
||||
signedOrder.makerTokenAmount,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
signedOrder.makerTokenAddress, signedOrder.maker, senderAddress, fillMakerTokenAmount,
|
||||
TradeSide.Maker, TransferType.Trade,
|
||||
signedOrder.makerTokenAddress,
|
||||
signedOrder.maker,
|
||||
senderAddress,
|
||||
fillMakerTokenAmount,
|
||||
TradeSide.Maker,
|
||||
TransferType.Trade,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
signedOrder.takerTokenAddress, senderAddress, signedOrder.maker, fillTakerTokenAmount,
|
||||
TradeSide.Taker, TransferType.Trade,
|
||||
signedOrder.takerTokenAddress,
|
||||
senderAddress,
|
||||
signedOrder.maker,
|
||||
fillTakerTokenAmount,
|
||||
TradeSide.Taker,
|
||||
TransferType.Trade,
|
||||
);
|
||||
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||
fillTakerTokenAmount,
|
||||
@@ -48,7 +61,11 @@ export class OrderValidationUtils {
|
||||
signedOrder.makerFee,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount, TradeSide.Maker,
|
||||
zrxTokenAddress,
|
||||
signedOrder.maker,
|
||||
signedOrder.feeRecipient,
|
||||
makerFeeAmount,
|
||||
TradeSide.Maker,
|
||||
TransferType.Fee,
|
||||
);
|
||||
const takerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||
@@ -57,12 +74,17 @@ export class OrderValidationUtils {
|
||||
signedOrder.takerFee,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
zrxTokenAddress, senderAddress, signedOrder.feeRecipient, takerFeeAmount, TradeSide.Taker,
|
||||
zrxTokenAddress,
|
||||
senderAddress,
|
||||
signedOrder.feeRecipient,
|
||||
takerFeeAmount,
|
||||
TradeSide.Taker,
|
||||
TransferType.Fee,
|
||||
);
|
||||
}
|
||||
private static _validateRemainingFillAmountNotZeroOrThrow(
|
||||
takerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
|
||||
takerTokenAmount: BigNumber,
|
||||
unavailableTakerTokenAmount: BigNumber,
|
||||
) {
|
||||
if (takerTokenAmount.eq(unavailableTakerTokenAmount)) {
|
||||
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
@@ -74,24 +96,27 @@ export class OrderValidationUtils {
|
||||
throw new Error(ExchangeContractErrs.OrderFillExpired);
|
||||
}
|
||||
}
|
||||
private static _getPartialAmount(numerator: BigNumber, denominator: BigNumber,
|
||||
target: BigNumber): BigNumber {
|
||||
private static _getPartialAmount(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
|
||||
const fillMakerTokenAmount = numerator
|
||||
.mul(target)
|
||||
.div(denominator)
|
||||
.round(0);
|
||||
.mul(target)
|
||||
.div(denominator)
|
||||
.round(0);
|
||||
return fillMakerTokenAmount;
|
||||
}
|
||||
constructor(exchangeWrapper: ExchangeWrapper) {
|
||||
this._exchangeWrapper = exchangeWrapper;
|
||||
}
|
||||
public async validateOrderFillableOrThrowAsync(
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder, zrxTokenAddress: string,
|
||||
expectedFillTakerTokenAmount?: BigNumber): Promise<void> {
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||
signedOrder: SignedOrder,
|
||||
zrxTokenAddress: string,
|
||||
expectedFillTakerTokenAmount?: BigNumber,
|
||||
): Promise<void> {
|
||||
const orderHash = utils.getOrderHashHex(signedOrder);
|
||||
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||
signedOrder.takerTokenAmount, unavailableTakerTokenAmount,
|
||||
signedOrder.takerTokenAmount,
|
||||
unavailableTakerTokenAmount,
|
||||
);
|
||||
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
|
||||
let fillTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
|
||||
@@ -104,8 +129,12 @@ export class OrderValidationUtils {
|
||||
signedOrder.makerTokenAmount,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
signedOrder.makerTokenAddress, signedOrder.maker, signedOrder.taker, fillMakerTokenAmount,
|
||||
TradeSide.Maker, TransferType.Trade,
|
||||
signedOrder.makerTokenAddress,
|
||||
signedOrder.maker,
|
||||
signedOrder.taker,
|
||||
fillMakerTokenAmount,
|
||||
TradeSide.Maker,
|
||||
TransferType.Trade,
|
||||
);
|
||||
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||
fillTakerTokenAmount,
|
||||
@@ -113,14 +142,21 @@ export class OrderValidationUtils {
|
||||
signedOrder.makerFee,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount,
|
||||
TradeSide.Maker, TransferType.Fee,
|
||||
zrxTokenAddress,
|
||||
signedOrder.maker,
|
||||
signedOrder.feeRecipient,
|
||||
makerFeeAmount,
|
||||
TradeSide.Maker,
|
||||
TransferType.Fee,
|
||||
);
|
||||
}
|
||||
public async validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber, takerAddress: string,
|
||||
zrxTokenAddress: string): Promise<BigNumber> {
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
zrxTokenAddress: string,
|
||||
): Promise<BigNumber> {
|
||||
if (fillTakerTokenAmount.eq(0)) {
|
||||
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
|
||||
}
|
||||
@@ -130,22 +166,29 @@ export class OrderValidationUtils {
|
||||
}
|
||||
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||
signedOrder.takerTokenAmount, unavailableTakerTokenAmount,
|
||||
signedOrder.takerTokenAmount,
|
||||
unavailableTakerTokenAmount,
|
||||
);
|
||||
if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== takerAddress) {
|
||||
throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
|
||||
}
|
||||
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
|
||||
const remainingTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
|
||||
const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount) ?
|
||||
remainingTakerTokenAmount :
|
||||
fillTakerTokenAmount;
|
||||
const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount)
|
||||
? remainingTakerTokenAmount
|
||||
: fillTakerTokenAmount;
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, signedOrder, filledTakerTokenAmount, takerAddress, zrxTokenAddress,
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
filledTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
|
||||
const wouldRoundingErrorOccur = await this._exchangeWrapper.isRoundingErrorAsync(
|
||||
filledTakerTokenAmount, signedOrder.takerTokenAmount, signedOrder.makerTokenAmount,
|
||||
filledTakerTokenAmount,
|
||||
signedOrder.takerTokenAmount,
|
||||
signedOrder.makerTokenAmount,
|
||||
);
|
||||
if (wouldRoundingErrorOccur) {
|
||||
throw new Error(ExchangeContractErrs.OrderFillRoundingError);
|
||||
@@ -153,10 +196,18 @@ export class OrderValidationUtils {
|
||||
return filledTakerTokenAmount;
|
||||
}
|
||||
public async validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber, takerAddress: string, zrxTokenAddress: string): Promise<void> {
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
zrxTokenAddress: string,
|
||||
): Promise<void> {
|
||||
const filledTakerTokenAmount = await this.validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress,
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
if (filledTakerTokenAmount !== fillTakerTokenAmount) {
|
||||
throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
|
||||
import {ECSignature} from '../types';
|
||||
import { ECSignature } from '../types';
|
||||
|
||||
export const signatureUtils = {
|
||||
isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
||||
@@ -11,7 +11,8 @@ export const signatureUtils = {
|
||||
msgHashBuff,
|
||||
signature.v,
|
||||
ethUtil.toBuffer(signature.r),
|
||||
ethUtil.toBuffer(signature.s));
|
||||
ethUtil.toBuffer(signature.s),
|
||||
);
|
||||
const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
|
||||
return retrievedAddress === signerAddress;
|
||||
} catch (err) {
|
||||
@@ -34,7 +35,7 @@ export const signatureUtils = {
|
||||
return ecSignature;
|
||||
},
|
||||
parseSignatureHexAsRSV(signatureHex: string): ECSignature {
|
||||
const {v, r, s} = ethUtil.fromRpcSig(signatureHex);
|
||||
const { v, r, s } = ethUtil.fromRpcSig(signatureHex);
|
||||
const ecSignature: ECSignature = {
|
||||
v,
|
||||
r: ethUtil.bufferToHex(r),
|
||||
|
@@ -4,7 +4,7 @@ import * as ethABI from 'ethereumjs-abi';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {Order, SignedOrder, SolidityTypes} from '../types';
|
||||
import { Order, SignedOrder, SolidityTypes } from '../types';
|
||||
|
||||
export const utils = {
|
||||
/**
|
||||
@@ -29,20 +29,35 @@ export const utils = {
|
||||
spawnSwitchErr(name: string, value: any): Error {
|
||||
return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
|
||||
},
|
||||
getOrderHashHex(order: Order|SignedOrder): string {
|
||||
getOrderHashHex(order: Order | SignedOrder): string {
|
||||
const orderParts = [
|
||||
{value: order.exchangeContractAddress, type: SolidityTypes.Address},
|
||||
{value: order.maker, type: SolidityTypes.Address},
|
||||
{value: order.taker, type: SolidityTypes.Address},
|
||||
{value: order.makerTokenAddress, type: SolidityTypes.Address},
|
||||
{value: order.takerTokenAddress, type: SolidityTypes.Address},
|
||||
{value: order.feeRecipient, type: SolidityTypes.Address},
|
||||
{value: utils.bigNumberToBN(order.makerTokenAmount), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.takerTokenAmount), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.makerFee), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.takerFee), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.expirationUnixTimestampSec), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.salt), type: SolidityTypes.Uint256},
|
||||
{ value: order.exchangeContractAddress, type: SolidityTypes.Address },
|
||||
{ value: order.maker, type: SolidityTypes.Address },
|
||||
{ value: order.taker, type: SolidityTypes.Address },
|
||||
{ value: order.makerTokenAddress, type: SolidityTypes.Address },
|
||||
{ value: order.takerTokenAddress, type: SolidityTypes.Address },
|
||||
{ value: order.feeRecipient, type: SolidityTypes.Address },
|
||||
{
|
||||
value: utils.bigNumberToBN(order.makerTokenAmount),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: utils.bigNumberToBN(order.takerTokenAmount),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: utils.bigNumberToBN(order.makerFee),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: utils.bigNumberToBN(order.takerFee),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: utils.bigNumberToBN(order.expirationUnixTimestampSec),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{ value: utils.bigNumberToBN(order.salt), type: SolidityTypes.Uint256 },
|
||||
];
|
||||
const types = _.map(orderParts, o => o.type);
|
||||
const values = _.map(orderParts, o => o.value);
|
||||
|
@@ -1,16 +1,16 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
|
||||
import {ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx} from '../src';
|
||||
import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx } from '../src';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
chaiSetup.configure();
|
||||
@@ -41,11 +41,11 @@ describe('ZeroEx library', () => {
|
||||
|
||||
// Check that all nested web3 wrapper instances return the updated provider
|
||||
const nestedWeb3WrapperProvider = (zeroEx as any)._web3Wrapper.getCurrentProvider();
|
||||
expect((nestedWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
||||
expect(nestedWeb3WrapperProvider.zeroExTestId).to.be.a('number');
|
||||
const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getCurrentProvider();
|
||||
expect((exchangeWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
||||
expect(exchangeWeb3WrapperProvider.zeroExTestId).to.be.a('number');
|
||||
const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getCurrentProvider();
|
||||
expect((tokenRegistryWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
||||
expect(tokenRegistryWeb3WrapperProvider.zeroExTestId).to.be.a('number');
|
||||
});
|
||||
});
|
||||
describe('#isValidSignature', () => {
|
||||
@@ -58,22 +58,25 @@ describe('ZeroEx library', () => {
|
||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||
};
|
||||
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||
it('should return false if the data doesn\'t pertain to the signature & address', async () => {
|
||||
it("should return false if the data doesn't pertain to the signature & address", async () => {
|
||||
expect(ZeroEx.isValidSignature('0x0', signature, address)).to.be.false();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
|
||||
).to.become(false);
|
||||
});
|
||||
it('should return false if the address doesn\'t pertain to the signature & data', async () => {
|
||||
it("should return false if the address doesn't pertain to the signature & data", async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
|
||||
expect(ZeroEx.isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature,
|
||||
validUnrelatedAddress),
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
|
||||
dataHex,
|
||||
signature,
|
||||
validUnrelatedAddress,
|
||||
),
|
||||
).to.become(false);
|
||||
});
|
||||
it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => {
|
||||
const wrongSignature = _.assign({}, signature, {v: 28});
|
||||
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
|
||||
const wrongSignature = _.assign({}, signature, { v: 28 });
|
||||
expect(ZeroEx.isValidSignature(dataHex, wrongSignature, address)).to.be.false();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
|
||||
@@ -117,8 +120,9 @@ describe('ZeroEx library', () => {
|
||||
it('should throw if invalid baseUnit amount supplied as argument', () => {
|
||||
const invalidBaseUnitAmount = new BigNumber(1000000000.4);
|
||||
const decimals = 6;
|
||||
expect(() => ZeroEx.toUnitAmount(invalidBaseUnitAmount, decimals))
|
||||
.to.throw('amount should be in baseUnits (no decimals), found value: 1000000000.4');
|
||||
expect(() => ZeroEx.toUnitAmount(invalidBaseUnitAmount, decimals)).to.throw(
|
||||
'amount should be in baseUnits (no decimals), found value: 1000000000.4',
|
||||
);
|
||||
});
|
||||
it('Should return the expected unit amount for the decimals passed in', () => {
|
||||
const baseUnitAmount = new BigNumber(1000000000);
|
||||
@@ -139,8 +143,9 @@ describe('ZeroEx library', () => {
|
||||
it('should throw if unitAmount has more decimals then specified as the max decimal precision', () => {
|
||||
const unitAmount = new BigNumber(0.823091);
|
||||
const decimals = 5;
|
||||
expect(() => ZeroEx.toBaseUnitAmount(unitAmount, decimals))
|
||||
.to.throw('Invalid unit amount: 0.823091 - Too many decimal places');
|
||||
expect(() => ZeroEx.toBaseUnitAmount(unitAmount, decimals)).to.throw(
|
||||
'Invalid unit amount: 0.823091 - Too many decimal places',
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('#getOrderHashHex', () => {
|
||||
@@ -167,10 +172,11 @@ describe('ZeroEx library', () => {
|
||||
it('throws a readable error message if taker format is invalid', async () => {
|
||||
const orderWithInvalidtakerFormat = {
|
||||
...order,
|
||||
taker: null as any as string,
|
||||
taker: (null as any) as string,
|
||||
};
|
||||
// tslint:disable-next-line:max-line-length
|
||||
const expectedErrorMessage = 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
const expectedErrorMessage =
|
||||
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
expect(() => ZeroEx.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
|
||||
});
|
||||
});
|
||||
@@ -199,15 +205,15 @@ describe('ZeroEx library', () => {
|
||||
it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
|
||||
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
|
||||
// tslint:disable-next-line: max-line-length
|
||||
const signature = '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
|
||||
const signature =
|
||||
'0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3',
|
||||
s: '0x050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb02',
|
||||
};
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync')
|
||||
.returns(Promise.resolve(signature)),
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync').returns(Promise.resolve(signature)),
|
||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
||||
];
|
||||
|
||||
@@ -217,15 +223,15 @@ describe('ZeroEx library', () => {
|
||||
it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
|
||||
const orderHash = '0xc793e33ffded933b76f2f48d9aa3339fc090399d5e7f5dec8d3660f5480793f7';
|
||||
// tslint:disable-next-line: max-line-length
|
||||
const signature = '0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
|
||||
const signature =
|
||||
'0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0xc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee0',
|
||||
s: '0x2dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960',
|
||||
};
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync')
|
||||
.returns(Promise.resolve(signature)),
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync').returns(Promise.resolve(signature)),
|
||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
||||
];
|
||||
|
||||
@@ -271,8 +277,9 @@ describe('ZeroEx library', () => {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress())
|
||||
.to.be.equal(ZeroEx.NULL_ADDRESS);
|
||||
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal(
|
||||
ZeroEx.NULL_ADDRESS,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import * as fs from 'fs';
|
||||
import HDWalletProvider = require('truffle-hdwallet-provider');
|
||||
|
||||
import {ZeroEx} from '../src';
|
||||
import { ZeroEx } from '../src';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
|
||||
chaiSetup.configure();
|
||||
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import {ZeroEx} from '../src';
|
||||
import {assert} from '../src/utils/assert';
|
||||
import { ZeroEx } from '../src';
|
||||
import { assert } from '../src/utils/assert';
|
||||
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { constants } from './utils/constants';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
@@ -19,22 +19,25 @@ describe('Assertion library', () => {
|
||||
it('throws when address is invalid', async () => {
|
||||
const address = '0xdeadbeef';
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, address, (zeroEx as any)._web3Wrapper))
|
||||
.to.be.rejectedWith(`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`);
|
||||
return expect(
|
||||
assert.isSenderAddressAsync(varName, address, (zeroEx as any)._web3Wrapper),
|
||||
).to.be.rejectedWith(`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`);
|
||||
});
|
||||
it('throws when address is unavailable', async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper))
|
||||
.to.be.rejectedWith(
|
||||
`Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
return expect(
|
||||
assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper),
|
||||
).to.be.rejectedWith(
|
||||
`Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
});
|
||||
it('doesn\'t throw if address is available', async () => {
|
||||
it("doesn't throw if address is available", async () => {
|
||||
const availableAddress = (await zeroEx.getAvailableAddressesAsync())[0];
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper))
|
||||
.to.become(undefined);
|
||||
return expect(
|
||||
assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper),
|
||||
).to.become(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
@@ -17,13 +17,13 @@ import {
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {artifacts} from '../src/artifacts';
|
||||
import {DoneCallback} from '../src/types';
|
||||
import { artifacts } from '../src/artifacts';
|
||||
import { DoneCallback } from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -167,10 +167,12 @@ describe('EtherTokenWrapper', () => {
|
||||
done();
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback);
|
||||
zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -186,10 +188,12 @@ describe('EtherTokenWrapper', () => {
|
||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback);
|
||||
zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, allowanceAmount,
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
addressWithoutFunds,
|
||||
allowanceAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -204,11 +208,8 @@ describe('EtherTokenWrapper', () => {
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback);
|
||||
await zeroEx.etherToken.depositAsync(
|
||||
etherTokenAddress, depositAmount, addressWithETH,
|
||||
);
|
||||
zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback);
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => {
|
||||
@@ -222,14 +223,14 @@ describe('EtherTokenWrapper', () => {
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
done();
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(
|
||||
etherTokenAddress, depositAmount, addressWithETH,
|
||||
);
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Withdrawal, indexFilterValues, callback);
|
||||
await zeroEx.etherToken.withdrawAsync(
|
||||
etherTokenAddress, withdrawalAmount, addressWithETH,
|
||||
etherTokenAddress,
|
||||
EtherTokenEvents.Withdrawal,
|
||||
indexFilterValues,
|
||||
callback,
|
||||
);
|
||||
await zeroEx.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => {
|
||||
@@ -238,7 +239,10 @@ describe('EtherTokenWrapper', () => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled,
|
||||
etherTokenAddress,
|
||||
EtherTokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
const callbackToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done();
|
||||
@@ -247,10 +251,16 @@ describe('EtherTokenWrapper', () => {
|
||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackToBeCalled,
|
||||
etherTokenAddress,
|
||||
EtherTokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callbackToBeCalled,
|
||||
);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -261,10 +271,17 @@ describe('EtherTokenWrapper', () => {
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
const subscriptionToken = zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
||||
etherTokenAddress,
|
||||
EtherTokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
zeroEx.etherToken.unsubscribe(subscriptionToken);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
etherTokenAddress,
|
||||
addressWithETH,
|
||||
addressWithoutFunds,
|
||||
transferAmount,
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
@@ -291,7 +308,10 @@ describe('EtherTokenWrapper', () => {
|
||||
const eventName = EtherTokenEvents.Approval;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
etherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
@@ -305,7 +325,10 @@ describe('EtherTokenWrapper', () => {
|
||||
const eventName = EtherTokenEvents.Deposit;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<DepositContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
etherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
@@ -319,7 +342,10 @@ describe('EtherTokenWrapper', () => {
|
||||
const differentEventName = EtherTokenEvents.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync(
|
||||
etherTokenAddress, differentEventName, blockRange, indexFilterValues,
|
||||
etherTokenAddress,
|
||||
differentEventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
@@ -333,7 +359,10 @@ describe('EtherTokenWrapper', () => {
|
||||
_owner: addressWithETH,
|
||||
};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
etherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
|
@@ -1,18 +1,16 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
LogEvent,
|
||||
} from '../src';
|
||||
import {EventWatcher} from '../src/order_watcher/event_watcher';
|
||||
import {DoneCallback} from '../src/types';
|
||||
import { LogEvent } from '../src';
|
||||
import { EventWatcher } from '../src/order_watcher/event_watcher';
|
||||
import { DoneCallback } from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -38,7 +36,7 @@ describe('EventWatcher', () => {
|
||||
blockNumber: null,
|
||||
data: '',
|
||||
logIndex: null,
|
||||
topics: [ '0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567' ],
|
||||
topics: ['0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567'],
|
||||
transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
|
||||
transactionIndex: 0,
|
||||
};
|
||||
@@ -48,7 +46,7 @@ describe('EventWatcher', () => {
|
||||
blockNumber: null,
|
||||
data: '',
|
||||
logIndex: null,
|
||||
topics: [ '0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567' ],
|
||||
topics: ['0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567'],
|
||||
transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
|
||||
transactionIndex: 0,
|
||||
};
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
|
||||
import {ExchangeContractErrs, Token, ZeroEx} from '../src';
|
||||
import {BlockParamLiteral, TradeSide, TransferType} from '../src/types';
|
||||
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
|
||||
import { ExchangeContractErrs, Token, ZeroEx } from '../src';
|
||||
import { BlockParamLiteral, TradeSide, TransferType } from '../src/types';
|
||||
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -45,17 +45,31 @@ describe('ExchangeTransferSimulator', () => {
|
||||
beforeEach(() => {
|
||||
exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest);
|
||||
});
|
||||
it('throws if the user doesn\'t have enough allowance', async () => {
|
||||
return expect(exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance);
|
||||
it("throws if the user doesn't have enough allowance", async () => {
|
||||
return expect(
|
||||
exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress,
|
||||
sender,
|
||||
recipient,
|
||||
transferAmount,
|
||||
TradeSide.Taker,
|
||||
TransferType.Trade,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance);
|
||||
});
|
||||
it('throws if the user doesn\'t have enough balance', async () => {
|
||||
it("throws if the user doesn't have enough balance", async () => {
|
||||
txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
return expect(exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Maker, TransferType.Trade,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
|
||||
return expect(
|
||||
exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress,
|
||||
sender,
|
||||
recipient,
|
||||
transferAmount,
|
||||
TradeSide.Maker,
|
||||
TransferType.Trade,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
|
||||
});
|
||||
it('updates balances and proxyAllowance after transfer', async () => {
|
||||
txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
|
||||
@@ -63,7 +77,12 @@ describe('ExchangeTransferSimulator', () => {
|
||||
txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
await exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
||||
exampleTokenAddress,
|
||||
sender,
|
||||
recipient,
|
||||
transferAmount,
|
||||
TradeSide.Taker,
|
||||
TransferType.Trade,
|
||||
);
|
||||
const store = (exchangeTransferSimulator as any)._store;
|
||||
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
||||
@@ -73,13 +92,18 @@ describe('ExchangeTransferSimulator', () => {
|
||||
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
|
||||
expect(senderProxyAllowance).to.be.bignumber.equal(0);
|
||||
});
|
||||
it('doesn\'t update proxyAllowance after transfer if unlimited', async () => {
|
||||
it("doesn't update proxyAllowance after transfer if unlimited", async () => {
|
||||
txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
await exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
||||
exampleTokenAddress,
|
||||
sender,
|
||||
recipient,
|
||||
transferAmount,
|
||||
TradeSide.Taker,
|
||||
TransferType.Trade,
|
||||
);
|
||||
const store = (exchangeTransferSimulator as any)._store;
|
||||
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
@@ -17,13 +17,13 @@ import {
|
||||
Token,
|
||||
ZeroEx,
|
||||
} from '../src';
|
||||
import {BlockParamLiteral, DoneCallback} from '../src/types';
|
||||
import { BlockParamLiteral, DoneCallback } from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { FillScenarios } from './utils/fill_scenarios';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -80,10 +80,18 @@ describe('ExchangeWrapper', () => {
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const partialFillTakerAmount = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderFillRequests = [
|
||||
{
|
||||
@@ -103,7 +111,11 @@ describe('ExchangeWrapper', () => {
|
||||
const fillableAmount = new BigNumber(5);
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
orderFillRequests = [
|
||||
{
|
||||
@@ -113,18 +125,23 @@ describe('ExchangeWrapper', () => {
|
||||
];
|
||||
});
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
|
||||
shouldValidate: true,
|
||||
}),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
|
||||
shouldValidate: false,
|
||||
}),
|
||||
).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -133,57 +150,78 @@ describe('ExchangeWrapper', () => {
|
||||
const fillableAmount = new BigNumber(5);
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
});
|
||||
describe('successful fills', () => {
|
||||
it('should fill a valid order', async () => {
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
0,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
0,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount.minus(takerTokenFillAmount),
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
takerTokenFillAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
takerTokenFillAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount.minus(takerTokenFillAmount),
|
||||
);
|
||||
});
|
||||
it('should partially fill a valid order', async () => {
|
||||
const partialFillAmount = new BigNumber(3);
|
||||
await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, partialFillAmount, takerAddress);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(partialFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(partialFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount.minus(partialFillAmount),
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
partialFillAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
partialFillAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount.minus(partialFillAmount),
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
const emptyFillableAmount = new BigNumber(0);
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
|
||||
shouldValidate: true,
|
||||
}),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
|
||||
shouldValidate: false,
|
||||
}),
|
||||
).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -209,57 +247,96 @@ describe('ExchangeWrapper', () => {
|
||||
describe('successful fills', () => {
|
||||
it('should fill a valid order', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
0,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
0,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount.minus(takerTokenFillAmount),
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
takerTokenFillAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
takerTokenFillAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount.minus(takerTokenFillAmount),
|
||||
);
|
||||
});
|
||||
it('should partially fill the valid order', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
const partialFillAmount = new BigNumber(3);
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
signedOrder,
|
||||
partialFillAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(partialFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(partialFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount.minus(partialFillAmount),
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
|
||||
partialFillAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
partialFillAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
|
||||
fillableAmount.minus(partialFillAmount),
|
||||
);
|
||||
});
|
||||
it('should fill the valid orders with fees', async () => {
|
||||
const makerFee = new BigNumber(1);
|
||||
const takerFee = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
|
||||
makerAddress, takerAddress, fillableAmount, feeRecipient,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
feeRecipient,
|
||||
);
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient))
|
||||
.to.be.bignumber.equal(makerFee.plus(takerFee));
|
||||
expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient)).to.be.bignumber.equal(
|
||||
makerFee.plus(takerFee),
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
@@ -267,25 +344,48 @@ describe('ExchangeWrapper', () => {
|
||||
const emptyFillTakerAmount = new BigNumber(0);
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
});
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder,
|
||||
emptyFillTakerAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder,
|
||||
emptyFillTakerAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
{
|
||||
shouldValidate: true,
|
||||
},
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder,
|
||||
emptyFillTakerAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
{
|
||||
shouldValidate: false,
|
||||
},
|
||||
),
|
||||
).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -297,11 +397,19 @@ describe('ExchangeWrapper', () => {
|
||||
let orderFillBatch: OrderFillRequest[];
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder);
|
||||
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
|
||||
});
|
||||
@@ -319,13 +427,20 @@ describe('ExchangeWrapper', () => {
|
||||
];
|
||||
});
|
||||
it('should throw if a batch is empty', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
[], shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
|
||||
return expect(
|
||||
zeroEx.exchange.batchFillOrdersAsync(
|
||||
[],
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
});
|
||||
it('should successfully fill multiple orders', async () => {
|
||||
const txHash = await zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
orderFillBatch,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
|
||||
@@ -348,21 +463,37 @@ describe('ExchangeWrapper', () => {
|
||||
];
|
||||
});
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
|
||||
return expect(
|
||||
zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
{
|
||||
shouldValidate: true,
|
||||
},
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
{
|
||||
shouldValidate: false,
|
||||
},
|
||||
),
|
||||
).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -375,24 +506,40 @@ describe('ExchangeWrapper', () => {
|
||||
const fillUpToAmount = fillableAmount.plus(fillableAmount).minus(1);
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder);
|
||||
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
|
||||
signedOrders = [signedOrder, anotherSignedOrder];
|
||||
});
|
||||
describe('successful batch fills', () => {
|
||||
it('should throw if a batch is empty', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
[], fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrdersUpToAsync(
|
||||
[],
|
||||
fillUpToAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
});
|
||||
it('should successfully fill up to specified amount', async () => {
|
||||
const txHash = await zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
signedOrders,
|
||||
fillUpToAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
|
||||
@@ -405,21 +552,40 @@ describe('ExchangeWrapper', () => {
|
||||
describe('order transaction options', () => {
|
||||
const emptyFillUpToAmount = new BigNumber(0);
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders,
|
||||
emptyFillUpToAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders,
|
||||
emptyFillUpToAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
{
|
||||
shouldValidate: true,
|
||||
},
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders,
|
||||
emptyFillUpToAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
{
|
||||
shouldValidate: false,
|
||||
},
|
||||
),
|
||||
).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -440,7 +606,11 @@ describe('ExchangeWrapper', () => {
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
orderHashHex = ZeroEx.getOrderHashHex(signedOrder);
|
||||
});
|
||||
@@ -456,18 +626,23 @@ describe('ExchangeWrapper', () => {
|
||||
describe('order transaction options', () => {
|
||||
const emptyCancelTakerTokenAmount = new BigNumber(0);
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
|
||||
shouldValidate: true,
|
||||
}),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
|
||||
shouldValidate: false,
|
||||
}),
|
||||
).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -477,7 +652,11 @@ describe('ExchangeWrapper', () => {
|
||||
let cancelBatch: OrderCancellationRequest[];
|
||||
beforeEach(async () => {
|
||||
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
|
||||
cancelBatch = [
|
||||
@@ -494,15 +673,21 @@ describe('ExchangeWrapper', () => {
|
||||
describe('failed batch cancels', () => {
|
||||
it('should throw when orders have different makers', async () => {
|
||||
const signedOrderWithDifferentMaker = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, takerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
takerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync([
|
||||
cancelBatch[0],
|
||||
{
|
||||
order: signedOrderWithDifferentMaker,
|
||||
takerTokenCancelAmount: cancelAmount,
|
||||
},
|
||||
])).to.be.rejectedWith(ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
|
||||
return expect(
|
||||
zeroEx.exchange.batchCancelOrdersAsync([
|
||||
cancelBatch[0],
|
||||
{
|
||||
order: signedOrderWithDifferentMaker,
|
||||
takerTokenCancelAmount: cancelAmount,
|
||||
},
|
||||
]),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
|
||||
});
|
||||
});
|
||||
describe('successful batch cancels', () => {
|
||||
@@ -531,18 +716,23 @@ describe('ExchangeWrapper', () => {
|
||||
];
|
||||
});
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch)).to.be.rejectedWith(
|
||||
ExchangeContractErrs.OrderCancelAmountZero,
|
||||
);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
|
||||
shouldValidate: true,
|
||||
}),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
|
||||
shouldValidate: false,
|
||||
}),
|
||||
).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -566,7 +756,11 @@ describe('ExchangeWrapper', () => {
|
||||
fillableAmount = new BigNumber(5);
|
||||
partialFillAmount = new BigNumber(2);
|
||||
signedOrder = await fillScenarios.createPartiallyFilledSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, partialFillAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
partialFillAmount,
|
||||
);
|
||||
orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
});
|
||||
@@ -590,8 +784,7 @@ describe('ExchangeWrapper', () => {
|
||||
return expect(zeroEx.exchange.getFilledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
|
||||
});
|
||||
it('should return zero if passed a valid but non-existent orderHash', async () => {
|
||||
const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(NON_EXISTENT_ORDER_HASH,
|
||||
);
|
||||
const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
|
||||
expect(filledValueT).to.be.bignumber.equal(0);
|
||||
});
|
||||
it('should return the filledValueT for a valid and partially filled orderHash', async () => {
|
||||
@@ -641,7 +834,11 @@ describe('ExchangeWrapper', () => {
|
||||
beforeEach(async () => {
|
||||
fillableAmount = new BigNumber(5);
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
});
|
||||
afterEach(async () => {
|
||||
@@ -654,42 +851,35 @@ 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 = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
|
||||
expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogFill);
|
||||
done();
|
||||
};
|
||||
zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogFill, indexFilterValues, callback,
|
||||
);
|
||||
zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callback);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
signedOrder,
|
||||
takerTokenFillAmountInBaseUnits,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<LogCancelContractEventArgs>) => {
|
||||
expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogCancel);
|
||||
done();
|
||||
};
|
||||
zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogCancel, indexFilterValues, callback,
|
||||
);
|
||||
zeroEx.exchange.subscribe(ExchangeEvents.LogCancel, indexFilterValues, callback);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled,
|
||||
);
|
||||
zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled);
|
||||
|
||||
const newProvider = web3Factory.getRpcProvider();
|
||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||
@@ -698,11 +888,11 @@ describe('ExchangeWrapper', () => {
|
||||
expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogFill);
|
||||
done();
|
||||
};
|
||||
zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogFill, indexFilterValues, callback,
|
||||
);
|
||||
zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callback);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
signedOrder,
|
||||
takerTokenFillAmountInBaseUnits,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
})().catch(done);
|
||||
@@ -713,11 +903,15 @@ describe('ExchangeWrapper', () => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
const subscriptionToken = zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled,
|
||||
ExchangeEvents.LogFill,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
zeroEx.exchange.unsubscribe(subscriptionToken);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
signedOrder,
|
||||
takerTokenFillAmountInBaseUnits,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
done();
|
||||
@@ -736,13 +930,18 @@ describe('ExchangeWrapper', () => {
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
it('get\'s the same hash as the local function', async () => {
|
||||
it("get's the same hash as the local function", async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
const orderHashFromContract = await (zeroEx.exchange as any)
|
||||
._getOrderHashHexUsingContractCallAsync(signedOrder);
|
||||
const orderHashFromContract = await (zeroEx.exchange as any)._getOrderHashHexUsingContractCallAsync(
|
||||
signedOrder,
|
||||
);
|
||||
expect(orderHash).to.equal(orderHashFromContract);
|
||||
});
|
||||
});
|
||||
@@ -773,10 +972,17 @@ describe('ExchangeWrapper', () => {
|
||||
});
|
||||
it('should get logs with decoded args emitted by LogFill', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
signedOrder,
|
||||
fillableAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = ExchangeEvents.LogFill;
|
||||
@@ -787,10 +993,17 @@ describe('ExchangeWrapper', () => {
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
signedOrder,
|
||||
fillableAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const differentEventName = ExchangeEvents.LogCancel;
|
||||
@@ -800,19 +1013,33 @@ describe('ExchangeWrapper', () => {
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
signedOrder,
|
||||
fillableAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const differentMakerAddress = userAddresses[2];
|
||||
const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, differentMakerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
differentMakerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
anotherSignedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
anotherSignedOrder,
|
||||
fillableAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
@@ -821,7 +1048,9 @@ describe('ExchangeWrapper', () => {
|
||||
maker: differentMakerAddress,
|
||||
};
|
||||
const logs = await zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
|
||||
eventName, blockRange, indexFilterValues,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
@@ -6,18 +6,18 @@ import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ZeroEx} from '../src/0x';
|
||||
import {ExpirationWatcher} from '../src/order_watcher/expiration_watcher';
|
||||
import {DoneCallback, Token} from '../src/types';
|
||||
import {constants} from '../src/utils/constants';
|
||||
import {utils} from '../src/utils/utils';
|
||||
import { ZeroEx } from '../src/0x';
|
||||
import { ExpirationWatcher } from '../src/order_watcher/expiration_watcher';
|
||||
import { DoneCallback, Token } from '../src/types';
|
||||
import { constants } from '../src/utils/constants';
|
||||
import { utils } from '../src/utils/utils';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants as testConstants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants as testConstants } from './utils/constants';
|
||||
import { FillScenarios } from './utils/fill_scenarios';
|
||||
import { reportCallbackErrors } from './utils/report_callback_errors';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -62,7 +62,7 @@ describe('ExpirationWatcher', () => {
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
const sinonTimerConfig = {shouldAdvanceTime: true} as any;
|
||||
const sinonTimerConfig = { shouldAdvanceTime: true } as any;
|
||||
// This constructor has incorrect types
|
||||
timer = Sinon.useFakeTimers(sinonTimerConfig);
|
||||
currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
|
||||
@@ -78,7 +78,11 @@ describe('ExpirationWatcher', () => {
|
||||
const orderLifetimeSec = 60;
|
||||
const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
expirationUnixTimestampSec,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
@@ -92,12 +96,16 @@ describe('ExpirationWatcher', () => {
|
||||
timer.tick(orderLifetimeSec * 1000);
|
||||
})().catch(done);
|
||||
});
|
||||
it('doesn\'t emit events before order expires', (done: DoneCallback) => {
|
||||
it("doesn't emit events before order expires", (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const orderLifetimeSec = 60;
|
||||
const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
expirationUnixTimestampSec,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
@@ -118,11 +126,19 @@ describe('ExpirationWatcher', () => {
|
||||
const order1ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order1Lifetime);
|
||||
const order2ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order2Lifetime);
|
||||
const signedOrder1 = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
order1ExpirationUnixTimestampSec,
|
||||
);
|
||||
const signedOrder2 = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
order2ExpirationUnixTimestampSec,
|
||||
);
|
||||
const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
@@ -15,14 +15,14 @@ import {
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {DoneCallback} from '../src/types';
|
||||
import { DoneCallback } from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { FillScenarios } from './utils/fill_scenarios';
|
||||
import { reportCallbackErrors } from './utils/report_callback_errors';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
const TIMEOUT_MS = 150;
|
||||
|
||||
@@ -71,7 +71,11 @@ describe('OrderStateWatcher', () => {
|
||||
describe('#removeOrder', async () => {
|
||||
it('should successfully remove existing order', async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -89,10 +93,18 @@ describe('OrderStateWatcher', () => {
|
||||
});
|
||||
it('should no-op when removing a non-existing order', async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
const nonExistentOrderHash = `0x${orderHash.substr(2).split('').reverse().join('')}`;
|
||||
const nonExistentOrderHash = `0x${orderHash
|
||||
.substr(2)
|
||||
.split('')
|
||||
.reverse()
|
||||
.join('')}`;
|
||||
zeroEx.orderStateWatcher.removeOrder(nonExistentOrderHash);
|
||||
});
|
||||
});
|
||||
@@ -102,8 +114,7 @@ describe('OrderStateWatcher', () => {
|
||||
});
|
||||
it('should fail when trying to subscribe twice', async () => {
|
||||
zeroEx.orderStateWatcher.subscribe(_.noop);
|
||||
expect(() => zeroEx.orderStateWatcher.subscribe(_.noop))
|
||||
.to.throw(ZeroExError.SubscriptionAlreadyPresent);
|
||||
expect(() => zeroEx.orderStateWatcher.subscribe(_.noop)).to.throw(ZeroExError.SubscriptionAlreadyPresent);
|
||||
});
|
||||
});
|
||||
describe('tests with cleanup', async () => {
|
||||
@@ -115,7 +126,11 @@ describe('OrderStateWatcher', () => {
|
||||
it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -133,7 +148,11 @@ describe('OrderStateWatcher', () => {
|
||||
it('should not emit an orderState event when irrelevant Transfer event received', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
@@ -152,7 +171,11 @@ describe('OrderStateWatcher', () => {
|
||||
it('should emit orderStateInvalid when maker moves balance backing watched order', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -172,7 +195,11 @@ describe('OrderStateWatcher', () => {
|
||||
it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -188,14 +215,21 @@ describe('OrderStateWatcher', () => {
|
||||
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
||||
signedOrder,
|
||||
fillableAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
taker,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateValid when watched order partially filled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
@@ -211,16 +245,21 @@ describe('OrderStateWatcher', () => {
|
||||
const remainingMakerBalance = makerBalance.sub(fillAmountInBaseUnits);
|
||||
const remainingFillable = fillableAmount.minus(fillAmountInBaseUnits);
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingFillable);
|
||||
remainingFillable,
|
||||
);
|
||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingFillable);
|
||||
remainingFillable,
|
||||
);
|
||||
expect(orderRelevantState.makerBalance).to.be.bignumber.equal(remainingMakerBalance);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
||||
signedOrder,
|
||||
fillAmountInBaseUnits,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
taker,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -229,8 +268,15 @@ describe('OrderStateWatcher', () => {
|
||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
|
||||
const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), 18);
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker, taker, fillableAmount,
|
||||
taker);
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
makerFee,
|
||||
takerFee,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
taker,
|
||||
);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
done();
|
||||
});
|
||||
@@ -245,7 +291,11 @@ describe('OrderStateWatcher', () => {
|
||||
const takerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(10), decimals);
|
||||
const makerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(20), decimals);
|
||||
signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, makerFillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
makerFillableAmount,
|
||||
takerFillableAmount,
|
||||
);
|
||||
const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
@@ -257,22 +307,31 @@ describe('OrderStateWatcher', () => {
|
||||
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(16), decimals));
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(16), decimals),
|
||||
);
|
||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(8), decimals));
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(8), decimals),
|
||||
);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
||||
signedOrder,
|
||||
fillAmountInBaseUnits,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
taker,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should equal approved amount when approved amount is lowest', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
|
||||
const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||
@@ -282,9 +341,11 @@ describe('OrderStateWatcher', () => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
changedMakerApprovalAmount);
|
||||
changedMakerApprovalAmount,
|
||||
);
|
||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||
changedMakerApprovalAmount);
|
||||
changedMakerApprovalAmount,
|
||||
);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
@@ -294,7 +355,11 @@ describe('OrderStateWatcher', () => {
|
||||
it('should equal balance amount when balance amount is lowest', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
@@ -308,14 +373,15 @@ describe('OrderStateWatcher', () => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingAmount);
|
||||
remainingAmount,
|
||||
);
|
||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingAmount);
|
||||
remainingAmount,
|
||||
);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.transferAsync(
|
||||
makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount);
|
||||
await zeroEx.token.transferAsync(makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should equal remaining amount when partially cancelled and order has fees', (done: DoneCallback) => {
|
||||
@@ -324,8 +390,15 @@ describe('OrderStateWatcher', () => {
|
||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||
const feeRecipient = taker;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
makerFee,
|
||||
takerFee,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
feeRecipient,
|
||||
);
|
||||
|
||||
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
||||
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
||||
@@ -336,7 +409,8 @@ describe('OrderStateWatcher', () => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingTokenAmount);
|
||||
remainingTokenAmount,
|
||||
);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
@@ -349,8 +423,15 @@ describe('OrderStateWatcher', () => {
|
||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||
const feeRecipient = taker;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
makerFee,
|
||||
takerFee,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
feeRecipient,
|
||||
);
|
||||
|
||||
const remainingFeeAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||
|
||||
@@ -362,13 +443,18 @@ describe('OrderStateWatcher', () => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingFeeAmount);
|
||||
remainingFeeAmount,
|
||||
);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, remainingFeeAmount);
|
||||
await zeroEx.token.transferAsync(
|
||||
makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferTokenAmount);
|
||||
makerToken.address,
|
||||
maker,
|
||||
ZeroEx.NULL_ADDRESS,
|
||||
transferTokenAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should calculate full amount when all available and non-divisible', (done: DoneCallback) => {
|
||||
@@ -377,8 +463,15 @@ describe('OrderStateWatcher', () => {
|
||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
const feeRecipient = taker;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
makerFee,
|
||||
takerFee,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
feeRecipient,
|
||||
);
|
||||
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
@@ -386,19 +479,27 @@ describe('OrderStateWatcher', () => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
fillableAmount);
|
||||
fillableAmount,
|
||||
);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.setProxyAllowanceAsync(
|
||||
makerToken.address, maker, ZeroEx.toBaseUnitAmount(new BigNumber(100), decimals));
|
||||
makerToken.address,
|
||||
maker,
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(100), decimals),
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
it('should emit orderStateInvalid when watched order cancelled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -419,7 +520,11 @@ describe('OrderStateWatcher', () => {
|
||||
(async () => {
|
||||
const remainingFillableAmountInBaseUnits = new BigNumber(100);
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -433,14 +538,19 @@ describe('OrderStateWatcher', () => {
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.exchange.cancelOrderAsync(
|
||||
signedOrder, fillableAmount.minus(remainingFillableAmountInBaseUnits),
|
||||
signedOrder,
|
||||
fillableAmount.minus(remainingFillableAmountInBaseUnits),
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateValid when watched order partially cancelled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
makerToken.address,
|
||||
takerToken.address,
|
||||
maker,
|
||||
taker,
|
||||
fillableAmount,
|
||||
);
|
||||
|
||||
const cancelAmountInBaseUnits = new BigNumber(2);
|
||||
|
@@ -1,19 +1,19 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError} from '../src';
|
||||
import {BlockParamLiteral, TradeSide, TransferType} from '../src/types';
|
||||
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
|
||||
import {OrderValidationUtils} from '../src/utils/order_validation_utils';
|
||||
import { ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError } from '../src';
|
||||
import { BlockParamLiteral, TradeSide, TransferType } from '../src/types';
|
||||
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
|
||||
import { OrderValidationUtils } from '../src/utils/order_validation_utils';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { FillScenarios } from './utils/fill_scenarios';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -62,108 +62,152 @@ describe('OrderValidation', () => {
|
||||
describe('validateOrderFillableOrThrowAsync', () => {
|
||||
it('should succeed if the order is fillable', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
||||
signedOrder,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||
});
|
||||
it('should succeed if the order is asymmetric and fillable', async () => {
|
||||
const makerFillableAmount = fillableAmount;
|
||||
const takerFillableAmount = fillableAmount.minus(4);
|
||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
makerFillableAmount, takerFillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
||||
signedOrder,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerFillableAmount,
|
||||
takerFillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||
});
|
||||
it('should throw when the order is fully filled or cancelled', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
||||
signedOrder,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith(
|
||||
ExchangeContractErrs.OrderRemainingFillAmountZero,
|
||||
);
|
||||
});
|
||||
it('should throw when order is expired', async () => {
|
||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, expirationInPast,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
expirationInPast,
|
||||
);
|
||||
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith(
|
||||
ExchangeContractErrs.OrderFillExpired,
|
||||
);
|
||||
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
||||
signedOrder,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
|
||||
});
|
||||
});
|
||||
describe('validateFillOrderAndThrowIfInvalidAsync', () => {
|
||||
it('should throw when the fill amount is zero', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
const zeroFillAmount = new BigNumber(0);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, zeroFillAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, zeroFillAmount, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should throw when the signature is invalid', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
// 27 <--> 28
|
||||
signedOrder.ecSignature.v = (28 - signedOrder.ecSignature.v) + 27;
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillableAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ZeroExError.InvalidSignature);
|
||||
signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27;
|
||||
return expect(
|
||||
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
|
||||
).to.be.rejectedWith(ZeroExError.InvalidSignature);
|
||||
});
|
||||
it('should throw when the order is fully filled or cancelled', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillableAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
});
|
||||
it('should throw when sender is not a taker', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
const nonTakerAddress = userAddresses[6];
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillTakerAmount, nonTakerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
|
||||
return expect(
|
||||
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillTakerAmount, nonTakerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
|
||||
});
|
||||
it('should throw when order is expired', async () => {
|
||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, expirationInPast,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
expirationInPast,
|
||||
);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillTakerAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
|
||||
return expect(
|
||||
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillTakerAmount, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
|
||||
});
|
||||
it('should throw when there a rounding error would have occurred', async () => {
|
||||
const makerAmount = new BigNumber(3);
|
||||
const takerAmount = new BigNumber(5);
|
||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
makerAmount, takerAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerAmount,
|
||||
takerAmount,
|
||||
);
|
||||
const fillTakerAmountThatCausesRoundingError = new BigNumber(3);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillTakerAmountThatCausesRoundingError, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillRoundingError);
|
||||
return expect(
|
||||
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder,
|
||||
fillTakerAmountThatCausesRoundingError,
|
||||
takerAddress,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillRoundingError);
|
||||
});
|
||||
});
|
||||
describe('#validateFillOrKillOrderAndThrowIfInvalidAsync', () => {
|
||||
it('should throw if remaining fillAmount is less then the desired fillAmount', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
const tooLargeFillAmount = new BigNumber(7);
|
||||
const fillAmountDifference = tooLargeFillAmount.minus(fillableAmount);
|
||||
@@ -172,9 +216,13 @@ describe('OrderValidation', () => {
|
||||
await zeroEx.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference);
|
||||
await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount);
|
||||
|
||||
return expect(zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
signedOrder, tooLargeFillAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
||||
return expect(
|
||||
zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
signedOrder,
|
||||
tooLargeFillAmount,
|
||||
takerAddress,
|
||||
),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
||||
});
|
||||
});
|
||||
describe('validateCancelOrderAndThrowIfInvalidAsync', () => {
|
||||
@@ -186,27 +234,38 @@ describe('OrderValidation', () => {
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
});
|
||||
it('should throw when cancel amount is zero', async () => {
|
||||
const zeroCancelAmount = new BigNumber(0);
|
||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
return expect(
|
||||
zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should throw when order is expired', async () => {
|
||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||
const expiredSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, expirationInPast,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
expirationInPast,
|
||||
);
|
||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
|
||||
return expect(
|
||||
zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
|
||||
});
|
||||
it('should throw when order is already cancelled or filled', async () => {
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
|
||||
return expect(
|
||||
zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
|
||||
});
|
||||
});
|
||||
describe('#validateFillOrderBalancesAllowancesThrowIfInvalidAsync', () => {
|
||||
@@ -224,82 +283,159 @@ describe('OrderValidation', () => {
|
||||
const makerFee = new BigNumber(2);
|
||||
const takerFee = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
|
||||
makerAddress, takerAddress, fillableAmount, feeRecipient,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
feeRecipient,
|
||||
);
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
|
||||
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,
|
||||
),
|
||||
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,
|
||||
),
|
||||
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,
|
||||
),
|
||||
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,
|
||||
),
|
||||
transferFromAsync
|
||||
.getCall(3)
|
||||
.calledWith(
|
||||
zrxTokenAddress,
|
||||
takerAddress,
|
||||
feeRecipient,
|
||||
bigNumberMatch(takerFee),
|
||||
TradeSide.Taker,
|
||||
TransferType.Fee,
|
||||
),
|
||||
).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,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
ZeroEx.NULL_ADDRESS,
|
||||
fillableAmount,
|
||||
feeRecipient,
|
||||
);
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
|
||||
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,
|
||||
),
|
||||
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,
|
||||
),
|
||||
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,
|
||||
),
|
||||
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,
|
||||
),
|
||||
transferFromAsync
|
||||
.getCall(3)
|
||||
.calledWith(
|
||||
zrxTokenAddress,
|
||||
takerAddress,
|
||||
feeRecipient,
|
||||
bigNumberMatch(takerFee),
|
||||
TradeSide.Taker,
|
||||
TransferType.Fee,
|
||||
),
|
||||
).to.be.true();
|
||||
});
|
||||
it('should correctly round the fillMakerTokenAmount', async () => {
|
||||
const makerTokenAmount = new BigNumber(3);
|
||||
const takerTokenAmount = new BigNumber(1);
|
||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, makerTokenAmount, takerTokenAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerTokenAmount,
|
||||
takerTokenAmount,
|
||||
);
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTransferSimulator, signedOrder, takerTokenAmount, takerAddress, zrxTokenAddress,
|
||||
exchangeTransferSimulator,
|
||||
signedOrder,
|
||||
takerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
expect(transferFromAsync.callCount).to.be.equal(4);
|
||||
const makerFillAmount = transferFromAsync.getCall(0).args[3];
|
||||
@@ -309,12 +445,22 @@ describe('OrderValidation', () => {
|
||||
const makerFee = new BigNumber(2);
|
||||
const takerFee = new BigNumber(4);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
||||
fillableAmount, ZeroEx.NULL_ADDRESS,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
ZeroEx.NULL_ADDRESS,
|
||||
);
|
||||
const fillTakerTokenAmount = fillableAmount.div(2).round(0);
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTransferSimulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress,
|
||||
exchangeTransferSimulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
const makerPartialFee = makerFee.div(2);
|
||||
const takerPartialFee = takerFee.div(2);
|
||||
|
@@ -2,11 +2,11 @@ import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import {ZeroEx} from '../src/0x';
|
||||
import {RemainingFillableCalculator} from '../src/order_watcher/remaining_fillable_calculator';
|
||||
import {ECSignature, SignedOrder} from '../src/types';
|
||||
import { ZeroEx } from '../src/0x';
|
||||
import { RemainingFillableCalculator } from '../src/order_watcher/remaining_fillable_calculator';
|
||||
import { ECSignature, SignedOrder } from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -26,29 +26,34 @@ describe('RemainingFillableCalculator', () => {
|
||||
const decimals: number = 4;
|
||||
const zero: BigNumber = new BigNumber(0);
|
||||
const zeroAddress = '0x0';
|
||||
const signature: ECSignature = {v: 27, r: '', s: ''};
|
||||
const signature: ECSignature = { v: 27, r: '', s: '' };
|
||||
beforeEach(async () => {
|
||||
[makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals)];
|
||||
[makerAmount, takerAmount, makerFeeAmount] = [
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals),
|
||||
];
|
||||
[transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount] = [
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals)];
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
|
||||
];
|
||||
});
|
||||
function buildSignedOrder(): SignedOrder {
|
||||
return { ecSignature: signature,
|
||||
exchangeContractAddress: zeroAddress,
|
||||
feeRecipient: zeroAddress,
|
||||
maker: zeroAddress,
|
||||
taker: zeroAddress,
|
||||
makerFee: makerFeeAmount,
|
||||
takerFee: zero,
|
||||
makerTokenAmount: makerAmount,
|
||||
takerTokenAmount: takerAmount,
|
||||
makerTokenAddress: makerToken,
|
||||
takerTokenAddress: takerToken,
|
||||
salt: zero,
|
||||
expirationUnixTimestampSec: zero };
|
||||
return {
|
||||
ecSignature: signature,
|
||||
exchangeContractAddress: zeroAddress,
|
||||
feeRecipient: zeroAddress,
|
||||
maker: zeroAddress,
|
||||
taker: zeroAddress,
|
||||
makerFee: makerFeeAmount,
|
||||
takerFee: zero,
|
||||
makerTokenAmount: makerAmount,
|
||||
takerTokenAmount: takerAmount,
|
||||
makerTokenAddress: makerToken,
|
||||
takerTokenAddress: takerToken,
|
||||
salt: zero,
|
||||
expirationUnixTimestampSec: zero,
|
||||
};
|
||||
}
|
||||
describe('Maker token is NOT ZRX', () => {
|
||||
before(async () => {
|
||||
@@ -57,23 +62,38 @@ describe('RemainingFillableCalculator', () => {
|
||||
it('calculates the correct amount when unfilled and funds available', () => {
|
||||
signedOrder = buildSignedOrder();
|
||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
||||
});
|
||||
it('calculates the correct amount when partially filled and funds available', () => {
|
||||
signedOrder = buildSignedOrder();
|
||||
remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
||||
});
|
||||
it('calculates the amount to be 0 when all fee funds are transferred', () => {
|
||||
signedOrder = buildSignedOrder();
|
||||
transferrableMakerFeeTokenAmount = zero;
|
||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
|
||||
});
|
||||
it('calculates the correct amount when balance is less than remaining fillable', () => {
|
||||
@@ -81,41 +101,58 @@ describe('RemainingFillableCalculator', () => {
|
||||
const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount);
|
||||
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount);
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
|
||||
});
|
||||
describe('Order to Fee Ratio is < 1', () => {
|
||||
beforeEach(async () => {
|
||||
[makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals)];
|
||||
[makerAmount, takerAmount, makerFeeAmount] = [
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
|
||||
];
|
||||
});
|
||||
it('calculates the correct amount when funds unavailable', () => {
|
||||
signedOrder = buildSignedOrder();
|
||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||
const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
|
||||
});
|
||||
});
|
||||
describe('Ratio is not evenly divisble', () => {
|
||||
beforeEach(async () => {
|
||||
[makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals)];
|
||||
[makerAmount, takerAmount, makerFeeAmount] = [
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
|
||||
];
|
||||
});
|
||||
it('calculates the correct amount when funds unavailable', () => {
|
||||
signedOrder = buildSignedOrder();
|
||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||
const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
|
||||
expect(calculatedFillableAmount.lessThanOrEqualTo(transferrableMakerTokenAmount)).to.be.true();
|
||||
expect(calculatedFillableAmount).to.be.bignumber.greaterThan(new BigNumber(0));
|
||||
@@ -134,15 +171,25 @@ describe('RemainingFillableCalculator', () => {
|
||||
transferrableMakerTokenAmount = makerAmount.plus(makerFeeAmount);
|
||||
transferrableMakerFeeTokenAmount = transferrableMakerTokenAmount;
|
||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
||||
});
|
||||
it('calculates the correct amount when partially filled and funds available', () => {
|
||||
signedOrder = buildSignedOrder();
|
||||
remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
||||
});
|
||||
it('calculates the amount to be 0 when all fee funds are transferred', () => {
|
||||
@@ -150,8 +197,13 @@ describe('RemainingFillableCalculator', () => {
|
||||
transferrableMakerTokenAmount = zero;
|
||||
transferrableMakerFeeTokenAmount = zero;
|
||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
|
||||
});
|
||||
it('calculates the correct amount when balance is less than remaining fillable', () => {
|
||||
@@ -163,8 +215,13 @@ describe('RemainingFillableCalculator', () => {
|
||||
|
||||
const orderToFeeRatio = signedOrder.makerTokenAmount.dividedToIntegerBy(signedOrder.makerFee);
|
||||
const expectedFillableAmount = new BigNumber(450980);
|
||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
||||
calculator = new RemainingFillableCalculator(
|
||||
signedOrder,
|
||||
isMakerTokenZRX,
|
||||
transferrableMakerTokenAmount,
|
||||
transferrableMakerFeeTokenAmount,
|
||||
remainingMakerTokenAmount,
|
||||
);
|
||||
const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
|
||||
const numberOfFillsInRatio = calculatedFillableAmount.dividedToIntegerBy(orderToFeeRatio);
|
||||
const calculatedFillableAmountPlusFees = calculatedFillableAmount.plus(numberOfFillsInRatio);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
@@ -6,19 +6,13 @@ import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
ApprovalContractEventArgs,
|
||||
DecodedLogEvent,
|
||||
Token,
|
||||
TokenEvents,
|
||||
ZeroEx,
|
||||
} from '../src';
|
||||
import {DoneCallback} from '../src/types';
|
||||
import { ApprovalContractEventArgs, DecodedLogEvent, Token, TokenEvents, ZeroEx } from '../src';
|
||||
import { DoneCallback } from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { reportCallbackErrors } from './utils/report_callback_errors';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -72,12 +66,8 @@ describe('SubscriptionTest', () => {
|
||||
done();
|
||||
},
|
||||
);
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync')
|
||||
.throws(new Error(errMsg)),
|
||||
];
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error(errMsg))];
|
||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -91,24 +81,16 @@ describe('SubscriptionTest', () => {
|
||||
done();
|
||||
},
|
||||
);
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'getLogsAsync')
|
||||
.throws(new Error(errMsg)),
|
||||
];
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getLogsAsync').throws(new Error(errMsg))];
|
||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => _.noop;
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync')
|
||||
.throws(new Error('JSON RPC error')),
|
||||
];
|
||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error('JSON RPC error'))];
|
||||
zeroEx.token.unsubscribeAll();
|
||||
done();
|
||||
})().catch(done);
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import {schemas, SchemaValidator} from '@0xproject/json-schemas';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
|
||||
import {Token, ZeroEx} from '../src';
|
||||
import { Token, ZeroEx } from '../src';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -19,10 +19,10 @@ const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7;
|
||||
describe('TokenRegistryWrapper', () => {
|
||||
let zeroEx: ZeroEx;
|
||||
let tokens: Token[];
|
||||
const tokenAddressBySymbol: {[symbol: string]: string} = {};
|
||||
const tokenAddressByName: {[symbol: string]: string} = {};
|
||||
const tokenBySymbol: {[symbol: string]: Token} = {};
|
||||
const tokenByName: {[symbol: string]: Token} = {};
|
||||
const tokenAddressBySymbol: { [symbol: string]: string } = {};
|
||||
const tokenAddressByName: { [symbol: string]: string } = {};
|
||||
const tokenBySymbol: { [symbol: string]: Token } = {};
|
||||
const tokenByName: { [symbol: string]: Token } = {};
|
||||
const registeredSymbol = 'ZRX';
|
||||
const registeredName = '0x Protocol Token';
|
||||
const unregisteredSymbol = 'MAL';
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import * as chai from 'chai';
|
||||
|
||||
import {ZeroEx} from '../src';
|
||||
import { ZeroEx } from '../src';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
@@ -16,12 +16,12 @@ import {
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {DoneCallback} from '../src/types';
|
||||
import { DoneCallback } from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { web3Factory } from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -74,17 +74,17 @@ describe('TokenWrapper', () => {
|
||||
it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => {
|
||||
const fromAddress = addressWithoutFunds;
|
||||
const toAddress = coinbase;
|
||||
return expect(zeroEx.token.transferAsync(
|
||||
token.address, fromAddress, toAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
||||
return expect(
|
||||
zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount),
|
||||
).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
||||
});
|
||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||
const fromAddress = coinbase;
|
||||
const toAddress = coinbase;
|
||||
return expect(zeroEx.token.transferAsync(
|
||||
nonExistentTokenAddress, fromAddress, toAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||
return expect(
|
||||
zeroEx.token.transferAsync(nonExistentTokenAddress, fromAddress, toAddress, transferAmount),
|
||||
).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||
});
|
||||
});
|
||||
describe('#transferFromAsync', () => {
|
||||
@@ -103,24 +103,22 @@ describe('TokenWrapper', () => {
|
||||
const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
|
||||
expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount);
|
||||
|
||||
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress,
|
||||
toAddress);
|
||||
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress, toAddress);
|
||||
expect(fromAddressAllowance).to.be.bignumber.equal(0);
|
||||
|
||||
return expect(zeroEx.token.transferFromAsync(
|
||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
||||
return expect(
|
||||
zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
|
||||
).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
||||
});
|
||||
it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress',
|
||||
async () => {
|
||||
it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress', async () => {
|
||||
const fromAddress = coinbase;
|
||||
const transferAmount = new BigNumber(42);
|
||||
|
||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount);
|
||||
|
||||
return expect(zeroEx.token.transferFromAsync(
|
||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
||||
return expect(
|
||||
zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
|
||||
).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
||||
});
|
||||
it('should fail to transfer tokens if fromAddress has insufficient balance', async () => {
|
||||
const fromAddress = addressWithoutFunds;
|
||||
@@ -130,13 +128,16 @@ describe('TokenWrapper', () => {
|
||||
expect(fromAddressBalance).to.be.bignumber.equal(0);
|
||||
|
||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
|
||||
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress,
|
||||
senderAddress);
|
||||
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(
|
||||
token.address,
|
||||
fromAddress,
|
||||
senderAddress,
|
||||
);
|
||||
expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount);
|
||||
|
||||
return expect(zeroEx.token.transferFromAsync(
|
||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
||||
return expect(
|
||||
zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
|
||||
).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
||||
});
|
||||
it('should successfully transfer tokens', async () => {
|
||||
const fromAddress = coinbase;
|
||||
@@ -147,17 +148,22 @@ describe('TokenWrapper', () => {
|
||||
const transferAmount = new BigNumber(42);
|
||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
|
||||
|
||||
await zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress,
|
||||
transferAmount);
|
||||
await zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount);
|
||||
const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
||||
});
|
||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||
const fromAddress = coinbase;
|
||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||
return expect(zeroEx.token.transferFromAsync(
|
||||
nonExistentTokenAddress, fromAddress, toAddress, senderAddress, new BigNumber(42),
|
||||
)).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||
return expect(
|
||||
zeroEx.token.transferFromAsync(
|
||||
nonExistentTokenAddress,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
senderAddress,
|
||||
new BigNumber(42),
|
||||
),
|
||||
).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||
});
|
||||
});
|
||||
describe('#getBalanceAsync', () => {
|
||||
@@ -172,8 +178,9 @@ describe('TokenWrapper', () => {
|
||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||
const ownerAddress = coinbase;
|
||||
return expect(zeroEx.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress))
|
||||
.to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||
return expect(zeroEx.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress)).to.be.rejectedWith(
|
||||
ZeroExError.TokenContractDoesNotExist,
|
||||
);
|
||||
});
|
||||
it('should return a balance of 0 for a non-existent owner address', async () => {
|
||||
const token = tokens[0];
|
||||
@@ -191,22 +198,25 @@ describe('TokenWrapper', () => {
|
||||
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
||||
});
|
||||
it('should return balance even when called with Web3 provider instance without addresses', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress);
|
||||
const expectedBalance = new BigNumber('1000000000000000000000000000');
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress);
|
||||
const expectedBalance = new BigNumber('1000000000000000000000000000');
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#setAllowanceAsync', () => {
|
||||
it('should set the spender\'s allowance', async () => {
|
||||
it("should set the spender's allowance", async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
const allowanceBeforeSet = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress,
|
||||
spenderAddress);
|
||||
const allowanceBeforeSet = await zeroEx.token.getAllowanceAsync(
|
||||
token.address,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
);
|
||||
const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
|
||||
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
|
||||
|
||||
@@ -219,7 +229,7 @@ describe('TokenWrapper', () => {
|
||||
});
|
||||
});
|
||||
describe('#setUnlimitedAllowanceAsync', () => {
|
||||
it('should set the unlimited spender\'s allowance', async () => {
|
||||
it("should set the unlimited spender's allowance", async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
@@ -241,10 +251,18 @@ describe('TokenWrapper', () => {
|
||||
);
|
||||
|
||||
await zeroEx.token.transferFromAsync(
|
||||
zrx.address, coinbase, userWithNormalAllowance, userWithNormalAllowance, transferAmount,
|
||||
zrx.address,
|
||||
coinbase,
|
||||
userWithNormalAllowance,
|
||||
userWithNormalAllowance,
|
||||
transferAmount,
|
||||
);
|
||||
await zeroEx.token.transferFromAsync(
|
||||
zrx.address, coinbase, userWithUnlimitedAllowance, userWithUnlimitedAllowance, transferAmount,
|
||||
zrx.address,
|
||||
coinbase,
|
||||
userWithUnlimitedAllowance,
|
||||
userWithUnlimitedAllowance,
|
||||
transferAmount,
|
||||
);
|
||||
|
||||
const finalBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
||||
@@ -300,7 +318,9 @@ describe('TokenWrapper', () => {
|
||||
await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
|
||||
|
||||
const allowance = await zeroExWithoutAccounts.token.getAllowanceAsync(
|
||||
token.address, ownerAddress, spenderAddress,
|
||||
token.address,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
);
|
||||
const expectedAllowance = amountInBaseUnits;
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
@@ -378,8 +398,7 @@ describe('TokenWrapper', () => {
|
||||
expect(args._value).to.be.bignumber.equal(transferAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callback);
|
||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callback);
|
||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -394,8 +413,7 @@ describe('TokenWrapper', () => {
|
||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -404,17 +422,13 @@ describe('TokenWrapper', () => {
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled,
|
||||
);
|
||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
||||
const callbackToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done();
|
||||
};
|
||||
const newProvider = web3Factory.getRpcProvider();
|
||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled,
|
||||
);
|
||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled);
|
||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -424,7 +438,11 @@ describe('TokenWrapper', () => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
const subscriptionToken = zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
||||
tokenAddress,
|
||||
TokenEvents.Transfer,
|
||||
indexFilterValues,
|
||||
callbackNeverToBeCalled,
|
||||
);
|
||||
zeroEx.token.unsubscribe(subscriptionToken);
|
||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||
done();
|
||||
@@ -450,7 +468,10 @@ describe('TokenWrapper', () => {
|
||||
const eventName = TokenEvents.Approval;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
||||
tokenAddress, eventName, blockRange, indexFilterValues,
|
||||
tokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
@@ -465,7 +486,10 @@ describe('TokenWrapper', () => {
|
||||
const differentEventName = TokenEvents.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.token.getLogsAsync(
|
||||
tokenAddress, differentEventName, blockRange, indexFilterValues,
|
||||
tokenAddress,
|
||||
differentEventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
@@ -479,7 +503,10 @@ describe('TokenWrapper', () => {
|
||||
_owner: coinbase,
|
||||
};
|
||||
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
||||
tokenAddress, eventName, blockRange, indexFilterValues,
|
||||
tokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
@@ -487,3 +514,4 @@ describe('TokenWrapper', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable:max-file-line-count
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import {SignedOrder, Token, ZeroEx} from '../../src';
|
||||
import {artifacts} from '../../src/artifacts';
|
||||
import {DummyTokenContract} from '../../src/contract_wrappers/generated/dummy_token';
|
||||
import {orderFactory} from '../utils/order_factory';
|
||||
import { SignedOrder, Token, ZeroEx } from '../../src';
|
||||
import { artifacts } from '../../src/artifacts';
|
||||
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
|
||||
import { orderFactory } from '../utils/order_factory';
|
||||
|
||||
import {constants} from './constants';
|
||||
import { constants } from './constants';
|
||||
|
||||
const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100);
|
||||
|
||||
@@ -17,8 +17,13 @@ export class FillScenarios {
|
||||
private _coinbase: string;
|
||||
private _zrxTokenAddress: string;
|
||||
private _exchangeContractAddress: string;
|
||||
constructor(zeroEx: ZeroEx, userAddresses: string[],
|
||||
tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) {
|
||||
constructor(
|
||||
zeroEx: ZeroEx,
|
||||
userAddresses: string[],
|
||||
tokens: Token[],
|
||||
zrxTokenAddress: string,
|
||||
exchangeContractAddress: string,
|
||||
) {
|
||||
this._zeroEx = zeroEx;
|
||||
this._userAddresses = userAddresses;
|
||||
this._tokens = tokens;
|
||||
@@ -31,7 +36,8 @@ export class FillScenarios {
|
||||
for (const token of this._tokens) {
|
||||
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
|
||||
const contractInstance = web3Wrapper.getContractInstance(
|
||||
artifacts.DummyTokenArtifact.abi, token.address,
|
||||
artifacts.DummyTokenArtifact.abi,
|
||||
token.address,
|
||||
);
|
||||
const defaults = {};
|
||||
const dummyToken = new DummyTokenContract(contractInstance, defaults);
|
||||
@@ -43,61 +49,110 @@ export class FillScenarios {
|
||||
}
|
||||
}
|
||||
}
|
||||
public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
|
||||
makerAddress: string, takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
expirationUnixTimestampSec?: BigNumber):
|
||||
Promise<SignedOrder> {
|
||||
public async createFillableSignedOrderAsync(
|
||||
makerTokenAddress: string,
|
||||
takerTokenAddress: string,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
expirationUnixTimestampSec?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
return this.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, fillableAmount, expirationUnixTimestampSec,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
expirationUnixTimestampSec,
|
||||
);
|
||||
}
|
||||
public async createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress: string, takerTokenAddress: string,
|
||||
makerFee: BigNumber, takerFee: BigNumber,
|
||||
makerAddress: string, takerAddress: string,
|
||||
makerTokenAddress: string,
|
||||
takerTokenAddress: string,
|
||||
makerFee: BigNumber,
|
||||
takerFee: BigNumber,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
feeRecepient: string, expirationUnixTimestampSec?: BigNumber,
|
||||
feeRecepient: string,
|
||||
expirationUnixTimestampSec?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
||||
fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
feeRecepient,
|
||||
expirationUnixTimestampSec,
|
||||
);
|
||||
}
|
||||
public async createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress: string, takerTokenAddress: string, makerAddress: string, takerAddress: string,
|
||||
makerFillableAmount: BigNumber, takerFillableAmount: BigNumber,
|
||||
expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
|
||||
makerTokenAddress: string,
|
||||
takerTokenAddress: string,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
makerFillableAmount: BigNumber,
|
||||
takerFillableAmount: BigNumber,
|
||||
expirationUnixTimestampSec?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const makerFee = new BigNumber(0);
|
||||
const takerFee = new BigNumber(0);
|
||||
const feeRecepient = constants.NULL_ADDRESS;
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
||||
makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerFillableAmount,
|
||||
takerFillableAmount,
|
||||
feeRecepient,
|
||||
expirationUnixTimestampSec,
|
||||
);
|
||||
}
|
||||
public async createPartiallyFilledSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
|
||||
takerAddress: string, fillableAmount: BigNumber,
|
||||
partialFillAmount: BigNumber) {
|
||||
public async createPartiallyFilledSignedOrderAsync(
|
||||
makerTokenAddress: string,
|
||||
takerTokenAddress: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
partialFillAmount: BigNumber,
|
||||
) {
|
||||
const [makerAddress] = this._userAddresses;
|
||||
const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, fillableAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = false;
|
||||
await this._zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
signedOrder,
|
||||
partialFillAmount,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
return signedOrder;
|
||||
}
|
||||
private async _createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress: string, takerTokenAddress: string,
|
||||
makerFee: BigNumber, takerFee: BigNumber,
|
||||
makerAddress: string, takerAddress: string,
|
||||
makerFillableAmount: BigNumber, takerFillableAmount: BigNumber,
|
||||
feeRecepient: string, expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
|
||||
|
||||
makerTokenAddress: string,
|
||||
takerTokenAddress: string,
|
||||
makerFee: BigNumber,
|
||||
takerFee: BigNumber,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
makerFillableAmount: BigNumber,
|
||||
takerFillableAmount: BigNumber,
|
||||
feeRecepient: string,
|
||||
expirationUnixTimestampSec?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
await Promise.all([
|
||||
this._increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
|
||||
this._increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
|
||||
@@ -107,14 +162,27 @@ export class FillScenarios {
|
||||
this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
|
||||
]);
|
||||
|
||||
const signedOrder = await orderFactory.createSignedOrderAsync(this._zeroEx,
|
||||
makerAddress, takerAddress, makerFee, takerFee,
|
||||
makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress,
|
||||
this._exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
|
||||
const signedOrder = await orderFactory.createSignedOrderAsync(
|
||||
this._zeroEx,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerFillableAmount,
|
||||
makerTokenAddress,
|
||||
takerFillableAmount,
|
||||
takerTokenAddress,
|
||||
this._exchangeContractAddress,
|
||||
feeRecepient,
|
||||
expirationUnixTimestampSec,
|
||||
);
|
||||
return signedOrder;
|
||||
}
|
||||
private async _increaseBalanceAndAllowanceAsync(
|
||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
tokenAddress: string,
|
||||
address: string,
|
||||
amount: BigNumber,
|
||||
): Promise<void> {
|
||||
if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
|
||||
return; // noop
|
||||
}
|
||||
@@ -123,16 +191,12 @@ export class FillScenarios {
|
||||
this._increaseAllowanceAsync(tokenAddress, address, amount),
|
||||
]);
|
||||
}
|
||||
private async _increaseBalanceAsync(
|
||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
private async _increaseBalanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
await this._zeroEx.token.transferAsync(tokenAddress, this._coinbase, address, amount);
|
||||
}
|
||||
private async _increaseAllowanceAsync(
|
||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
private async _increaseAllowanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
const oldMakerAllowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, address);
|
||||
const newMakerAllowance = oldMakerAllowance.plus(amount);
|
||||
await this._zeroEx.token.setProxyAllowanceAsync(
|
||||
tokenAddress, address, newMakerAllowance,
|
||||
);
|
||||
await this._zeroEx.token.setProxyAllowanceAsync(tokenAddress, address, newMakerAllowance);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {SignedOrder, ZeroEx} from '../../src';
|
||||
import { SignedOrder, ZeroEx } from '../../src';
|
||||
|
||||
export const orderFactory = {
|
||||
async createSignedOrderAsync(
|
||||
@@ -16,11 +16,12 @@ export const orderFactory = {
|
||||
takerTokenAddress: string,
|
||||
exchangeContractAddress: string,
|
||||
feeRecipient: string,
|
||||
expirationUnixTimestampSecIfExists?: BigNumber): Promise<SignedOrder> {
|
||||
expirationUnixTimestampSecIfExists?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite
|
||||
const expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSecIfExists) ?
|
||||
defaultExpirationUnixTimestampSec :
|
||||
expirationUnixTimestampSecIfExists;
|
||||
const expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSecIfExists)
|
||||
? defaultExpirationUnixTimestampSec
|
||||
: expirationUnixTimestampSecIfExists;
|
||||
const order = {
|
||||
maker,
|
||||
taker,
|
||||
@@ -37,7 +38,7 @@ export const orderFactory = {
|
||||
};
|
||||
const orderHash = ZeroEx.getOrderHashHex(order);
|
||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker);
|
||||
const signedOrder: SignedOrder = _.assign(order, {ecSignature});
|
||||
const signedOrder: SignedOrder = _.assign(order, { ecSignature });
|
||||
return signedOrder;
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {DoneCallback} from '../../src/types';
|
||||
import { DoneCallback } from '../../src/types';
|
||||
|
||||
export const reportCallbackErrors = (done: DoneCallback) => {
|
||||
return (f: (...args: any[]) => void) => {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {JSONRPCPayload} from '../../../src/types';
|
||||
import { JSONRPCPayload } from '../../../src/types';
|
||||
|
||||
/*
|
||||
* This class implements the web3-provider-engine subprovider interface and returns
|
||||
@@ -8,7 +8,7 @@ import {JSONRPCPayload} from '../../../src/types';
|
||||
export class EmptyWalletSubprovider {
|
||||
// This method needs to be here to satisfy the interface but linter wants it to be static.
|
||||
// tslint:disable-next-line:prefer-function-over-method
|
||||
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error|null, result: any) => void) {
|
||||
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error | null, result: any) => void) {
|
||||
switch (payload.method) {
|
||||
case 'eth_accounts':
|
||||
end(null, []);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import {JSONRPCPayload} from '../../../src/types';
|
||||
import { JSONRPCPayload } from '../../../src/types';
|
||||
|
||||
/*
|
||||
* This class implements the web3-provider-engine subprovider interface and returns
|
||||
@@ -15,7 +15,7 @@ export class FakeGasEstimateSubprovider {
|
||||
}
|
||||
// This method needs to be here to satisfy the interface but linter wants it to be static.
|
||||
// tslint:disable-next-line:prefer-function-over-method
|
||||
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error|null, result: any) => void) {
|
||||
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error | null, result: any) => void) {
|
||||
switch (payload.method) {
|
||||
case 'eth_estimateGas':
|
||||
end(null, this._constantGasAmount);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {InternalZeroExError, Token} from '../../src/types';
|
||||
import { InternalZeroExError, Token } from '../../src/types';
|
||||
|
||||
const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
|
||||
const WETH_TOKEN_SYMBOL = 'WETH';
|
||||
@@ -11,14 +11,14 @@ export class TokenUtils {
|
||||
this._tokens = tokens;
|
||||
}
|
||||
public getProtocolTokenOrThrow(): Token {
|
||||
const zrxToken = _.find(this._tokens, {symbol: PROTOCOL_TOKEN_SYMBOL});
|
||||
const zrxToken = _.find(this._tokens, { symbol: PROTOCOL_TOKEN_SYMBOL });
|
||||
if (_.isUndefined(zrxToken)) {
|
||||
throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
|
||||
}
|
||||
return zrxToken;
|
||||
}
|
||||
public getWethTokenOrThrow(): Token {
|
||||
const wethToken = _.find(this._tokens, {symbol: WETH_TOKEN_SYMBOL});
|
||||
const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL });
|
||||
if (_.isUndefined(wethToken)) {
|
||||
throw new Error(InternalZeroExError.WethNotInTokenRegistry);
|
||||
}
|
||||
|
@@ -6,10 +6,10 @@
|
||||
import ProviderEngine = require('web3-provider-engine');
|
||||
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
|
||||
|
||||
import {EmptyWalletSubprovider} from './subproviders/empty_wallet_subprovider';
|
||||
import {FakeGasEstimateSubprovider} from './subproviders/fake_gas_estimate_subprovider';
|
||||
import { EmptyWalletSubprovider } from './subproviders/empty_wallet_subprovider';
|
||||
import { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_subprovider';
|
||||
|
||||
import {constants} from './constants';
|
||||
import { constants } from './constants';
|
||||
|
||||
// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
|
||||
// because they are using the wrong XHR package.
|
||||
@@ -31,9 +31,11 @@ export const web3Factory = {
|
||||
provider.addProvider(new EmptyWalletSubprovider());
|
||||
}
|
||||
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_ESTIMATE));
|
||||
provider.addProvider(new RpcSubprovider({
|
||||
rpcUrl: constants.RPC_URL,
|
||||
}));
|
||||
provider.addProvider(
|
||||
new RpcSubprovider({
|
||||
rpcUrl: constants.RPC_URL,
|
||||
}),
|
||||
);
|
||||
provider.start();
|
||||
return provider;
|
||||
},
|
||||
|
Reference in New Issue
Block a user