aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/0x.js/package.json2
-rw-r--r--packages/abi-gen/package.json2
-rw-r--r--packages/assert/package.json2
-rw-r--r--packages/base-contract/package.json2
-rw-r--r--packages/connect/package.json4
-rw-r--r--packages/contract-wrappers/package.json2
-rw-r--r--packages/contracts/package.json2
-rw-r--r--packages/contracts/test/exchange/fill_order.ts11
-rw-r--r--packages/contracts/test/utils/fill_order_combinatorial_utils.ts7
-rw-r--r--packages/contracts/test/utils/order_factory_from_scenario.ts23
-rw-r--r--packages/contracts/test/utils/types.ts3
-rw-r--r--packages/dev-utils/package.json2
-rw-r--r--packages/ethereum-types/package.json2
-rw-r--r--packages/fill-scenarios/package.json2
-rw-r--r--packages/json-schemas/package.json2
-rw-r--r--packages/migrations/package.json2
-rw-r--r--packages/order-utils/CHANGELOG.json18
-rw-r--r--packages/order-utils/package.json2
-rw-r--r--packages/order-utils/src/index.ts2
-rw-r--r--packages/order-utils/src/market_utils.ts129
-rw-r--r--packages/order-utils/src/order_state_utils.ts95
-rw-r--r--packages/order-utils/src/rate_utils.ts48
-rw-r--r--packages/order-utils/src/sorting_utils.ts54
-rw-r--r--packages/order-utils/src/types.ts28
-rw-r--r--packages/order-utils/test/market_utils_test.ts50
-rw-r--r--packages/order-utils/test/order_state_utils_test.ts124
-rw-r--r--packages/order-utils/test/rate_utils_test.ts55
-rw-r--r--packages/order-utils/test/sorting_utils_test.ts67
-rw-r--r--packages/order-watcher/package.json2
-rw-r--r--packages/order-watcher/test/order_watcher_test.ts20
-rw-r--r--packages/react-docs-example/package.json2
-rw-r--r--packages/react-docs/package.json2
-rw-r--r--packages/react-shared/package.json2
-rw-r--r--packages/sol-compiler/package.json2
-rw-r--r--packages/sol-cov/package.json2
-rw-r--r--packages/sol-resolver/package.json2
-rw-r--r--packages/sra-report/package.json2
-rw-r--r--packages/subproviders/package.json2
-rw-r--r--packages/tslint-config/package.json2
-rw-r--r--packages/types/package.json2
-rw-r--r--packages/types/src/index.ts3
-rw-r--r--packages/typescript-typings/package.json2
-rw-r--r--packages/utils/package.json2
-rw-r--r--packages/web3-wrapper/package.json2
-rw-r--r--packages/website/package.json2
-rw-r--r--packages/website/ts/utils/utils.ts7
46 files changed, 618 insertions, 184 deletions
diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json
index 2daf40b54..bbb902b49 100644
--- a/packages/0x.js/package.json
+++ b/packages/0x.js/package.json
@@ -81,7 +81,7 @@
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"json-loader": "^0.5.4",
"make-promises-safe": "^1.1.0",
diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json
index 565fe4058..3e3494585 100644
--- a/packages/abi-gen/package.json
+++ b/packages/abi-gen/package.json
@@ -56,7 +56,7 @@
"@types/tmp": "^0.0.33",
"@types/yargs": "^10.0.0",
"chai": "^4.1.2",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^5.2.0",
diff --git a/packages/assert/package.json b/packages/assert/package.json
index d249b4cd1..64e60a1e1 100644
--- a/packages/assert/package.json
+++ b/packages/assert/package.json
@@ -36,7 +36,7 @@
"@types/mocha": "^2.2.42",
"@types/valid-url": "^1.0.2",
"chai": "^4.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json
index c5375ecf6..d31a02dda 100644
--- a/packages/base-contract/package.json
+++ b/packages/base-contract/package.json
@@ -34,7 +34,7 @@
"@0xproject/tslint-config": "^1.0.5",
"@types/lodash": "4.14.104",
"chai": "^4.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
diff --git a/packages/connect/package.json b/packages/connect/package.json
index de262a5c2..798f839b5 100644
--- a/packages/connect/package.json
+++ b/packages/connect/package.json
@@ -64,7 +64,7 @@
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.5",
"@0xproject/tslint-config": "^1.0.5",
- "@types/fetch-mock": "^5.12.2",
+ "@types/fetch-mock": "^6.0.3",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/query-string": "^5.0.1",
@@ -73,7 +73,7 @@
"async-child-process": "^1.1.1",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"fetch-mock": "^5.13.1",
"make-promises-safe": "^1.1.0",
diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json
index ae2867e6c..098c95ef0 100644
--- a/packages/contract-wrappers/package.json
+++ b/packages/contract-wrappers/package.json
@@ -57,7 +57,7 @@
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 01858894b..8bd808a27 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -59,7 +59,7 @@
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
diff --git a/packages/contracts/test/exchange/fill_order.ts b/packages/contracts/test/exchange/fill_order.ts
index 1494fe093..e79e2239e 100644
--- a/packages/contracts/test/exchange/fill_order.ts
+++ b/packages/contracts/test/exchange/fill_order.ts
@@ -104,6 +104,17 @@ describe('FillOrder Tests', () => {
};
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
});
+ it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount with zero decimals', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ makerAssetAmountScenario: OrderAssetAmountScenario.Small,
+ makerAssetDataScenario: AssetDataScenario.ERC20ZeroDecimals,
+ },
+ };
+ await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => {
const fillScenario = {
...defaultFillScenario,
diff --git a/packages/contracts/test/utils/fill_order_combinatorial_utils.ts b/packages/contracts/test/utils/fill_order_combinatorial_utils.ts
index 284c4a2db..f18ad0dd3 100644
--- a/packages/contracts/test/utils/fill_order_combinatorial_utils.ts
+++ b/packages/contracts/test/utils/fill_order_combinatorial_utils.ts
@@ -81,6 +81,12 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
erc20FiveDecimalTokenCount,
fiveDecimals,
);
+ const zeroDecimals = new BigNumber(0);
+ const erc20ZeroDecimalTokenCount = 2;
+ const [erc20ZeroDecimalTokenA, erc20ZeroDecimalTokenB] = await erc20Wrapper.deployDummyTokensAsync(
+ erc20ZeroDecimalTokenCount,
+ zeroDecimals,
+ );
const erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync();
@@ -119,6 +125,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
zrxToken.address,
[erc20EighteenDecimalTokenA.address, erc20EighteenDecimalTokenB.address],
[erc20FiveDecimalTokenA.address, erc20FiveDecimalTokenB.address],
+ [erc20ZeroDecimalTokenA.address, erc20ZeroDecimalTokenB.address],
erc721Token,
erc721Balances,
exchangeContract.address,
diff --git a/packages/contracts/test/utils/order_factory_from_scenario.ts b/packages/contracts/test/utils/order_factory_from_scenario.ts
index a908140b9..8e04db588 100644
--- a/packages/contracts/test/utils/order_factory_from_scenario.ts
+++ b/packages/contracts/test/utils/order_factory_from_scenario.ts
@@ -21,6 +21,8 @@ const POINT_ONE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(100_000_000_000_000_000)
const POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(50_000_000_000_000_000);
const TEN_UNITS_FIVE_DECIMALS = new BigNumber(1_000_000);
const FIVE_UNITS_FIVE_DECIMALS = new BigNumber(500_000);
+const TEN_UNITS_ZERO_DECIMALS = new BigNumber(10);
+const ONE_THOUSAND_UNITS_ZERO_DECIMALS = new BigNumber(1000);
const ONE_NFT_UNIT = new BigNumber(1);
export class OrderFactoryFromScenario {
@@ -28,6 +30,7 @@ export class OrderFactoryFromScenario {
private readonly _zrxAddress: string;
private readonly _nonZrxERC20EighteenDecimalTokenAddresses: string[];
private readonly _erc20FiveDecimalTokenAddresses: string[];
+ private readonly _erc20ZeroDecimalTokenAddresses: string[];
private readonly _erc721Token: DummyERC721TokenContract;
private readonly _erc721Balances: ERC721TokenIdsByOwner;
private readonly _exchangeAddress: string;
@@ -36,6 +39,7 @@ export class OrderFactoryFromScenario {
zrxAddress: string,
nonZrxERC20EighteenDecimalTokenAddresses: string[],
erc20FiveDecimalTokenAddresses: string[],
+ erc20ZeroDecimalTokenAddresses: string[],
erc721Token: DummyERC721TokenContract,
erc721Balances: ERC721TokenIdsByOwner,
exchangeAddress: string,
@@ -44,6 +48,7 @@ export class OrderFactoryFromScenario {
this._zrxAddress = zrxAddress;
this._nonZrxERC20EighteenDecimalTokenAddresses = nonZrxERC20EighteenDecimalTokenAddresses;
this._erc20FiveDecimalTokenAddresses = erc20FiveDecimalTokenAddresses;
+ this._erc20ZeroDecimalTokenAddresses = erc20ZeroDecimalTokenAddresses;
this._erc721Token = erc721Token;
this._erc721Balances = erc721Balances;
this._exchangeAddress = exchangeAddress;
@@ -89,6 +94,9 @@ export class OrderFactoryFromScenario {
erc721MakerAssetIds[0],
);
break;
+ case AssetDataScenario.ERC20ZeroDecimals:
+ makerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[0]);
+ break;
default:
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
}
@@ -109,6 +117,9 @@ export class OrderFactoryFromScenario {
erc721TakerAssetIds[0],
);
break;
+ case AssetDataScenario.ERC20ZeroDecimals:
+ takerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[1]);
+ break;
default:
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
}
@@ -126,6 +137,9 @@ export class OrderFactoryFromScenario {
case AssetDataScenario.ERC721:
makerAssetAmount = ONE_NFT_UNIT;
break;
+ case AssetDataScenario.ERC20ZeroDecimals:
+ makerAssetAmount = ONE_THOUSAND_UNITS_ZERO_DECIMALS;
+ break;
default:
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
}
@@ -142,6 +156,9 @@ export class OrderFactoryFromScenario {
case AssetDataScenario.ERC721:
makerAssetAmount = ONE_NFT_UNIT;
break;
+ case AssetDataScenario.ERC20ZeroDecimals:
+ makerAssetAmount = TEN_UNITS_ZERO_DECIMALS;
+ break;
default:
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
}
@@ -166,6 +183,9 @@ export class OrderFactoryFromScenario {
case AssetDataScenario.ERC721:
takerAssetAmount = ONE_NFT_UNIT;
break;
+ case AssetDataScenario.ERC20ZeroDecimals:
+ takerAssetAmount = ONE_THOUSAND_UNITS_ZERO_DECIMALS;
+ break;
default:
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
}
@@ -182,6 +202,9 @@ export class OrderFactoryFromScenario {
case AssetDataScenario.ERC721:
takerAssetAmount = ONE_NFT_UNIT;
break;
+ case AssetDataScenario.ERC20ZeroDecimals:
+ takerAssetAmount = TEN_UNITS_ZERO_DECIMALS;
+ break;
default:
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
}
diff --git a/packages/contracts/test/utils/types.ts b/packages/contracts/test/utils/types.ts
index 67313b647..481ee87d6 100644
--- a/packages/contracts/test/utils/types.ts
+++ b/packages/contracts/test/utils/types.ts
@@ -177,10 +177,11 @@ export enum ExpirationTimeSecondsScenario {
}
export enum AssetDataScenario {
- ERC721 = 'ERC721',
+ ERC20ZeroDecimals = 'ERC20_ZERO_DECIMALS',
ZRXFeeToken = 'ZRX_FEE_TOKEN',
ERC20FiveDecimals = 'ERC20_FIVE_DECIMALS',
ERC20NonZRXEighteenDecimals = 'ERC20_NON_ZRX_EIGHTEEN_DECIMALS',
+ ERC721 = 'ERC721',
}
export enum TakerAssetFillAmountScenario {
diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json
index 544ff23fa..79e75a06e 100644
--- a/packages/dev-utils/package.json
+++ b/packages/dev-utils/package.json
@@ -35,7 +35,7 @@
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"chai": "^4.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
diff --git a/packages/ethereum-types/package.json b/packages/ethereum-types/package.json
index c2092a1d3..4fa273c6a 100644
--- a/packages/ethereum-types/package.json
+++ b/packages/ethereum-types/package.json
@@ -37,7 +37,7 @@
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.5",
"@0xproject/tslint-config": "^1.0.5",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "5.11.0",
diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json
index 466e96258..ccc04caf8 100644
--- a/packages/fill-scenarios/package.json
+++ b/packages/fill-scenarios/package.json
@@ -33,7 +33,7 @@
"@0xproject/sol-compiler": "^1.0.5",
"@0xproject/tslint-config": "^1.0.5",
"@types/lodash": "4.14.104",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json
index a5941a971..062304585 100644
--- a/packages/json-schemas/package.json
+++ b/packages/json-schemas/package.json
@@ -60,7 +60,7 @@
"@types/lodash.values": "^4.3.3",
"@types/mocha": "^2.2.42",
"chai": "^4.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"lodash.foreach": "^4.5.0",
"make-promises-safe": "^1.1.0",
diff --git a/packages/migrations/package.json b/packages/migrations/package.json
index dc481a972..c1ef61257 100644
--- a/packages/migrations/package.json
+++ b/packages/migrations/package.json
@@ -44,7 +44,7 @@
"@0xproject/tslint-config": "^1.0.5",
"@0xproject/types": "^1.0.1-rc.4",
"@types/yargs": "^10.0.0",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json
index a81eb077d..86f0da65a 100644
--- a/packages/order-utils/CHANGELOG.json
+++ b/packages/order-utils/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.1-rc.4",
+ "changes": [
+ {
+ "note": "Remove rounding error being thrown when maker amount is very small",
+ "pr": 959
+ },
+ {
+ "note": "Added rateUtils and sortingUtils",
+ "pr": 953
+ },
+ {
+ "note":
+ "Update marketUtils api such that all optional parameters are bundled into one optional param and more defaults are provided",
+ "pr": 954
+ }
+ ]
+ },
+ {
"version": "1.0.1-rc.3",
"changes": [
{
diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json
index bedbdc6d2..07d6fa1b6 100644
--- a/packages/order-utils/package.json
+++ b/packages/order-utils/package.json
@@ -61,7 +61,7 @@
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts
index 681fbc904..2b1c92973 100644
--- a/packages/order-utils/src/index.ts
+++ b/packages/order-utils/src/index.ts
@@ -25,3 +25,5 @@ export { EIP712Utils } from './eip712_utils';
export { OrderValidationUtils } from './order_validation_utils';
export { ExchangeTransferSimulator } from './exchange_transfer_simulator';
export { marketUtils } from './market_utils';
+export { rateUtils } from './rate_utils';
+export { sortingUtils } from './sorting_utils';
diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts
index 681059ddf..a0a827546 100644
--- a/packages/order-utils/src/market_utils.ts
+++ b/packages/order-utils/src/market_utils.ts
@@ -1,46 +1,51 @@
import { schemas } from '@0xproject/json-schemas';
-import { SignedOrder } from '@0xproject/types';
+import { Order } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { assert } from './assert';
import { constants } from './constants';
+import { FindFeeOrdersThatCoverFeesForTargetOrdersOpts, FindOrdersThatCoverMakerAssetFillAmountOpts } from './types';
export const marketUtils = {
/**
- * Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount (taking into account on-chain balances,
- * allowances, and partial fills) in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last.
+ * Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount
+ * in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last order.
* Sort the input by ascending rate in order to get the subset of orders that will cost the least ETH.
- * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify the same makerAsset.
- * All orders should specify WETH as the takerAsset.
- * @param remainingFillableMakerAssetAmounts An array of BigNumbers corresponding to the signedOrders parameter.
- * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups
- * for these values.
- * @param makerAssetFillAmount The amount of makerAsset desired to be filled.
- * @param slippageBufferAmount An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills.
+ * @param orders An array of objects that extend the Order interface. All orders should specify the same makerAsset.
+ * All orders should specify WETH as the takerAsset.
+ * @param makerAssetFillAmount The amount of makerAsset desired to be filled.
+ * @param opts Optional arguments this function accepts.
* @return Resulting orders and remaining fill amount that could not be covered by the input.
*/
- findOrdersThatCoverMakerAssetFillAmount(
- signedOrders: SignedOrder[],
- remainingFillableMakerAssetAmounts: BigNumber[],
+ findOrdersThatCoverMakerAssetFillAmount<T extends Order>(
+ orders: T[],
makerAssetFillAmount: BigNumber,
- slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT,
- ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } {
- assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ opts?: FindOrdersThatCoverMakerAssetFillAmountOpts,
+ ): { resultOrders: T[]; remainingFillAmount: BigNumber } {
+ assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
+ assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount);
+ // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders
+ const remainingFillableMakerAssetAmounts = _.get(
+ opts,
+ 'remainingFillableMakerAssetAmounts',
+ _.map(orders, order => order.makerAssetAmount),
+ ) as BigNumber[];
_.forEach(remainingFillableMakerAssetAmounts, (amount, index) =>
assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount),
);
- assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount);
- assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount);
assert.assert(
- signedOrders.length === remainingFillableMakerAssetAmounts.length,
- 'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length',
+ orders.length === remainingFillableMakerAssetAmounts.length,
+ 'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length',
);
+ // try to get slippageBufferAmount from opts, if it's not there, default to 0
+ const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber;
+ assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount);
// calculate total amount of makerAsset needed to be filled
const totalFillAmount = makerAssetFillAmount.plus(slippageBufferAmount);
- // iterate through the signedOrders input from left to right until we have enough makerAsset to fill totalFillAmount
+ // iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount
const result = _.reduce(
- signedOrders,
+ orders,
({ resultOrders, remainingFillAmount }, order, index) => {
if (remainingFillAmount.lessThanOrEqualTo(constants.ZERO_AMOUNT)) {
return { resultOrders, remainingFillAmount: constants.ZERO_AMOUNT };
@@ -59,55 +64,61 @@ export const marketUtils = {
};
}
},
- { resultOrders: [] as SignedOrder[], remainingFillAmount: totalFillAmount },
+ { resultOrders: [] as T[], remainingFillAmount: totalFillAmount },
);
return result;
},
/**
- * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX (taking into account
- * on-chain balances, allowances, and partial fills) in order to fill the takerFees required by signedOrders plus a
- * slippageBufferAmount. Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of
+ * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX
+ * in order to fill the takerFees required by orders plus a slippageBufferAmount.
+ * Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of
* feeOrders that will cost the least ETH.
- * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as
- * the makerAsset and WETH as the takerAsset.
- * @param remainingFillableMakerAssetAmounts An array of BigNumbers corresponding to the signedOrders parameter.
- * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups
- * for these values.
- * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as
- * the makerAsset and WETH as the takerAsset.
- * @param remainingFillableFeeAmounts An array of BigNumbers corresponding to the signedFeeOrders parameter.
- * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups
- * for these values.
- * @param slippageBufferAmount An additional amount of fee to be covered by the result in case of trade collisions or partial fills.
+ * @param orders An array of objects that extend the Order interface. All orders should specify ZRX as
+ * the makerAsset and WETH as the takerAsset.
+ * @param feeOrders An array of objects that extend the Order interface. All orders should specify ZRX as
+ * the makerAsset and WETH as the takerAsset.
+ * @param opts Optional arguments this function accepts.
* @return Resulting orders and remaining fee amount that could not be covered by the input.
*/
- findFeeOrdersThatCoverFeesForTargetOrders(
- signedOrders: SignedOrder[],
- remainingFillableMakerAssetAmounts: BigNumber[],
- signedFeeOrders: SignedOrder[],
- remainingFillableFeeAmounts: BigNumber[],
- slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT,
- ): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } {
- assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ findFeeOrdersThatCoverFeesForTargetOrders<T extends Order>(
+ orders: T[],
+ feeOrders: T[],
+ opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts,
+ ): { resultOrders: T[]; remainingFeeAmount: BigNumber } {
+ assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
+ assert.doesConformToSchema('feeOrders', feeOrders, schemas.ordersSchema);
+ // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders
+ const remainingFillableMakerAssetAmounts = _.get(
+ opts,
+ 'remainingFillableMakerAssetAmounts',
+ _.map(orders, order => order.makerAssetAmount),
+ ) as BigNumber[];
_.forEach(remainingFillableMakerAssetAmounts, (amount, index) =>
assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount),
);
- assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
+ assert.assert(
+ orders.length === remainingFillableMakerAssetAmounts.length,
+ 'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length',
+ );
+ // try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from feeOrders
+ const remainingFillableFeeAmounts = _.get(
+ opts,
+ 'remainingFillableFeeAmounts',
+ _.map(feeOrders, order => order.makerAssetAmount),
+ ) as BigNumber[];
_.forEach(remainingFillableFeeAmounts, (amount, index) =>
assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount),
);
- assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount);
assert.assert(
- signedOrders.length === remainingFillableMakerAssetAmounts.length,
- 'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length',
+ feeOrders.length === remainingFillableFeeAmounts.length,
+ 'Expected feeOrders.length to equal opts.remainingFillableFeeAmounts.length',
);
- assert.assert(
- signedOrders.length === remainingFillableMakerAssetAmounts.length,
- 'Expected signedFeeOrders.length to equal remainingFillableFeeAmounts.length',
- );
- // calculate total amount of ZRX needed to fill signedOrders
+ // try to get slippageBufferAmount from opts, if it's not there, default to 0
+ const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber;
+ assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount);
+ // calculate total amount of ZRX needed to fill orders
const totalFeeAmount = _.reduce(
- signedOrders,
+ orders,
(accFees, order, index) => {
const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index];
const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable
@@ -118,10 +129,12 @@ export const marketUtils = {
constants.ZERO_AMOUNT,
);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
- signedFeeOrders,
- remainingFillableFeeAmounts,
+ feeOrders,
totalFeeAmount,
- slippageBufferAmount,
+ {
+ remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts,
+ slippageBufferAmount,
+ },
);
return {
resultOrders,
diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts
index 189bf4180..18fc18bf6 100644
--- a/packages/order-utils/src/order_state_utils.ts
+++ b/packages/order-utils/src/order_state_utils.ts
@@ -11,6 +11,7 @@ import { BigNumber } from '@0xproject/utils';
import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
import { orderHashUtils } from './order_hash';
+import { OrderValidationUtils } from './order_validation_utils';
import { RemainingFillableCalculator } from './remaining_fillable_calculator';
import { utils } from './utils';
@@ -22,9 +23,16 @@ interface SidedOrderRelevantState {
traderFeeProxyAllowance: BigNumber;
filledTakerAssetAmount: BigNumber;
remainingFillableAssetAmount: BigNumber;
+ isOrderCancelled: boolean;
}
-
-const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
+interface OrderValidResult {
+ isValid: true;
+}
+interface OrderInvalidResult {
+ isValid: false;
+ error: ExchangeContractErrs;
+}
+type OrderValidationResult = OrderValidResult | OrderInvalidResult;
export class OrderStateUtils {
private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher;
@@ -32,64 +40,56 @@ export class OrderStateUtils {
private static _validateIfOrderIsValid(
signedOrder: SignedOrder,
sidedOrderRelevantState: SidedOrderRelevantState,
- ): void {
+ ): OrderValidationResult {
const isMakerSide = sidedOrderRelevantState.isMakerSide;
+ if (sidedOrderRelevantState.isOrderCancelled) {
+ return { isValid: false, error: ExchangeContractErrs.OrderCancelled };
+ }
const availableTakerAssetAmount = signedOrder.takerAssetAmount.minus(
sidedOrderRelevantState.filledTakerAssetAmount,
);
if (availableTakerAssetAmount.eq(0)) {
- throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
+ return { isValid: false, error: ExchangeContractErrs.OrderRemainingFillAmountZero };
}
if (sidedOrderRelevantState.traderBalance.eq(0)) {
- throw new Error(
- isMakerSide
- ? ExchangeContractErrs.InsufficientMakerBalance
- : ExchangeContractErrs.InsufficientTakerBalance,
- );
+ const error = isMakerSide
+ ? ExchangeContractErrs.InsufficientMakerBalance
+ : ExchangeContractErrs.InsufficientTakerBalance;
+ return { isValid: false, error };
}
if (sidedOrderRelevantState.traderProxyAllowance.eq(0)) {
- throw new Error(
- isMakerSide
- ? ExchangeContractErrs.InsufficientMakerAllowance
- : ExchangeContractErrs.InsufficientTakerAllowance,
- );
+ const error = isMakerSide
+ ? ExchangeContractErrs.InsufficientMakerAllowance
+ : ExchangeContractErrs.InsufficientTakerAllowance;
+ return { isValid: false, error };
}
if (!signedOrder.makerFee.eq(0)) {
if (sidedOrderRelevantState.traderFeeBalance.eq(0)) {
- throw new Error(
- isMakerSide
- ? ExchangeContractErrs.InsufficientMakerFeeBalance
- : ExchangeContractErrs.InsufficientTakerFeeBalance,
- );
+ const error = isMakerSide
+ ? ExchangeContractErrs.InsufficientMakerFeeBalance
+ : ExchangeContractErrs.InsufficientTakerFeeBalance;
+ return { isValid: false, error };
}
if (sidedOrderRelevantState.traderFeeProxyAllowance.eq(0)) {
- throw new Error(
- isMakerSide
- ? ExchangeContractErrs.InsufficientMakerFeeAllowance
- : ExchangeContractErrs.InsufficientTakerFeeAllowance,
- );
+ const error = isMakerSide
+ ? ExchangeContractErrs.InsufficientMakerFeeAllowance
+ : ExchangeContractErrs.InsufficientTakerFeeAllowance;
+ return { isValid: false, error };
}
}
-
- let minFillableTakerAssetAmountWithinNoRoundingErrorRange;
- if (isMakerSide) {
- minFillableTakerAssetAmountWithinNoRoundingErrorRange = signedOrder.takerAssetAmount
- .dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
- .dividedBy(signedOrder.makerAssetAmount);
- } else {
- minFillableTakerAssetAmountWithinNoRoundingErrorRange = signedOrder.makerAssetAmount
- .dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
- .dividedBy(signedOrder.takerAssetAmount);
- }
-
- if (
- sidedOrderRelevantState.remainingFillableAssetAmount.lessThan(
- minFillableTakerAssetAmountWithinNoRoundingErrorRange,
- )
- ) {
- throw new Error(ExchangeContractErrs.OrderFillRoundingError);
+ const remainingTakerAssetAmount = signedOrder.takerAssetAmount.minus(
+ sidedOrderRelevantState.filledTakerAssetAmount,
+ );
+ const isRoundingError = OrderValidationUtils.isRoundingError(
+ remainingTakerAssetAmount,
+ signedOrder.takerAssetAmount,
+ signedOrder.makerAssetAmount,
+ );
+ if (isRoundingError) {
+ return { isValid: false, error: ExchangeContractErrs.OrderFillRoundingError };
}
+ return { isValid: true };
}
constructor(
balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher,
@@ -101,6 +101,7 @@ export class OrderStateUtils {
public async getOpenOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> {
const orderRelevantState = await this.getOpenOrderRelevantStateAsync(signedOrder);
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ const isOrderCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(orderHash);
const sidedOrderRelevantState = {
isMakerSide: true,
traderBalance: orderRelevantState.makerBalance,
@@ -109,20 +110,21 @@ export class OrderStateUtils {
traderFeeProxyAllowance: orderRelevantState.makerFeeProxyAllowance,
filledTakerAssetAmount: orderRelevantState.filledTakerAssetAmount,
remainingFillableAssetAmount: orderRelevantState.remainingFillableMakerAssetAmount,
+ isOrderCancelled,
};
- try {
- OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState);
+ const orderValidationResult = OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState);
+ if (orderValidationResult.isValid) {
const orderState: OrderStateValid = {
isValid: true,
orderHash,
orderRelevantState,
};
return orderState;
- } catch (err) {
+ } else {
const orderState: OrderStateInvalid = {
isValid: false,
orderHash,
- error: err.message,
+ error: orderValidationResult.error,
};
return orderState;
}
@@ -278,6 +280,7 @@ export class OrderStateUtils {
traderFeeProxyAllowance,
filledTakerAssetAmount,
remainingFillableAssetAmount,
+ isOrderCancelled,
};
return sidedOrderRelevantState;
}
diff --git a/packages/order-utils/src/rate_utils.ts b/packages/order-utils/src/rate_utils.ts
new file mode 100644
index 000000000..c9ca72c59
--- /dev/null
+++ b/packages/order-utils/src/rate_utils.ts
@@ -0,0 +1,48 @@
+import { schemas } from '@0xproject/json-schemas';
+import { Order } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+
+import { assert } from './assert';
+import { constants } from './constants';
+
+export const rateUtils = {
+ /**
+ * Takes an order and calculates the fee adjusted rate (takerAsset/makerAsset) by calculating how much takerAsset
+ * is required to cover the fees (feeRate * takerFee), adding the takerAssetAmount and dividing by makerAssetAmount
+ * @param order An object that conforms to the order interface
+ * @param feeRate The market rate of ZRX denominated in takerAssetAmount
+ * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX)
+ * Defaults to 0
+ * @return The rate (takerAsset/makerAsset) of the order adjusted for fees
+ */
+ getFeeAdjustedRateOfOrder(order: Order, feeRate: BigNumber = constants.ZERO_AMOUNT): BigNumber {
+ assert.doesConformToSchema('order', order, schemas.orderSchema);
+ assert.isBigNumber('feeRate', feeRate);
+ assert.assert(
+ feeRate.gte(constants.ZERO_AMOUNT),
+ `Expected feeRate: ${feeRate} to be greater than or equal to 0`,
+ );
+ const takerAssetAmountNeededToPayForFees = order.takerFee.mul(feeRate);
+ const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(order.takerAssetAmount);
+ const rate = totalTakerAssetAmount.div(order.makerAssetAmount);
+ return rate;
+ },
+ /**
+ * Takes a fee order (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) and calculates
+ * the fee adjusted rate (WETH/ZRX) by dividing the takerAssetAmount by the makerAmount minus the takerFee
+ * @param feeOrder An object that conforms to the order interface
+ * @return The rate (WETH/ZRX) of the fee order adjusted for fees
+ */
+ getFeeAdjustedRateOfFeeOrder(feeOrder: Order): BigNumber {
+ assert.doesConformToSchema('feeOrder', feeOrder, schemas.orderSchema);
+ const zrxAmountAfterFees = feeOrder.makerAssetAmount.sub(feeOrder.takerFee);
+ assert.assert(
+ zrxAmountAfterFees.greaterThan(constants.ZERO_AMOUNT),
+ `Expected takerFee: ${JSON.stringify(feeOrder.takerFee)} to be less than makerAssetAmount: ${JSON.stringify(
+ feeOrder.makerAssetAmount,
+ )}`,
+ );
+ const rate = feeOrder.takerAssetAmount.div(zrxAmountAfterFees);
+ return rate;
+ },
+};
diff --git a/packages/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts
new file mode 100644
index 000000000..8811bcaf8
--- /dev/null
+++ b/packages/order-utils/src/sorting_utils.ts
@@ -0,0 +1,54 @@
+import { schemas } from '@0xproject/json-schemas';
+import { Order } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+
+import { assert } from './assert';
+import { constants } from './constants';
+import { rateUtils } from './rate_utils';
+
+export const sortingUtils = {
+ /**
+ * Takes an array of orders and sorts them by takerAsset/makerAsset rate in ascending order (best rate first).
+ * Adjusts the rate of each order according to the feeRate and takerFee for that order.
+ * @param orders An array of objects that extend the Order interface. All orders should specify ZRX as
+ * the makerAsset and WETH as the takerAsset.
+ * @param feeRate The market rate of ZRX denominated in takerAssetAmount
+ * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX)
+ * Defaults to 0
+ * @return The input orders sorted by rate in ascending order
+ */
+ sortOrdersByFeeAdjustedRate<T extends Order>(orders: T[], feeRate: BigNumber = constants.ZERO_AMOUNT): T[] {
+ assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
+ assert.isBigNumber('feeRate', feeRate);
+ const rateCalculator = (order: Order) => rateUtils.getFeeAdjustedRateOfOrder(order, feeRate);
+ const sortedOrders = sortOrders(orders, rateCalculator);
+ return sortedOrders;
+ },
+ /**
+ * Takes an array of fee orders (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH)
+ * and sorts them by rate in ascending order (best rate first). Adjusts the rate according to the takerFee.
+ * @param feeOrders An array of objects that extend the Order interface. All orders should specify ZRX as
+ * the makerAsset and WETH as the takerAsset.
+ * @return The input orders sorted by rate in ascending order
+ */
+ sortFeeOrdersByFeeAdjustedRate(feeOrders: Order[]): Order[] {
+ assert.doesConformToSchema('feeOrders', feeOrders, schemas.ordersSchema);
+ const rateCalculator = rateUtils.getFeeAdjustedRateOfFeeOrder.bind(rateUtils);
+ const sortedOrders = sortOrders(feeOrders, rateCalculator);
+ return sortedOrders;
+ },
+};
+
+type RateCalculator = (order: Order) => BigNumber;
+
+// takes an array of orders, copies them, and sorts the copy based on the rate definition provided by rateCalculator
+function sortOrders<T extends Order>(orders: T[], rateCalculator: RateCalculator): T[] {
+ const copiedOrders = _.cloneDeep(orders);
+ copiedOrders.sort((firstOrder, secondOrder) => {
+ const firstOrderRate = rateCalculator(firstOrder);
+ const secondOrderRate = rateCalculator(secondOrder);
+ return firstOrderRate.comparedTo(secondOrderRate);
+ });
+ return copiedOrders;
+}
diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts
index 1fbd8cf7b..2e9c79d80 100644
--- a/packages/order-utils/src/types.ts
+++ b/packages/order-utils/src/types.ts
@@ -41,3 +41,31 @@ export interface CreateOrderOpts {
salt?: BigNumber;
expirationTimeSeconds?: BigNumber;
}
+
+/**
+ * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter.
+ * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values.
+ * Defaults to `makerAssetAmount` values from the orders param.
+ * slippageBufferAmount: An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills.
+ * Defaults to 0
+ */
+export interface FindOrdersThatCoverMakerAssetFillAmountOpts {
+ remainingFillableMakerAssetAmounts?: BigNumber[];
+ slippageBufferAmount?: BigNumber;
+}
+
+/**
+ * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter.
+ * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values.
+ * Defaults to `makerAssetAmount` values from the orders param.
+ * remainingFillableFeeAmounts: An array of BigNumbers corresponding to the feeOrders parameter.
+ * You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups for these values.
+ * Defaults to `makerAssetAmount` values from the feeOrders param.
+ * slippageBufferAmount: An additional amount of fee to be covered by the result in case of trade collisions or partial fills.
+ * Defaults to 0
+ */
+export interface FindFeeOrdersThatCoverFeesForTargetOrdersOpts {
+ remainingFillableMakerAssetAmounts?: BigNumber[];
+ remainingFillableFeeAmounts?: BigNumber[];
+ slippageBufferAmount?: BigNumber;
+}
diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts
index 21c0a4802..109420a02 100644
--- a/packages/order-utils/test/market_utils_test.ts
+++ b/packages/order-utils/test/market_utils_test.ts
@@ -18,7 +18,6 @@ describe('marketUtils', () => {
const fillAmount = new BigNumber(10);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
[],
- [],
fillAmount,
);
expect(resultOrders).to.be.empty;
@@ -34,8 +33,6 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
- const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
// try to fill 20 units of makerAsset
// include 10 units of slippageBufferAmount
@@ -43,9 +40,10 @@ describe('marketUtils', () => {
const slippageBufferAmount = new BigNumber(10);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
- slippageBufferAmount,
+ {
+ slippageBufferAmount,
+ },
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -57,9 +55,10 @@ describe('marketUtils', () => {
const slippageBufferAmount = new BigNumber(10);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
- slippageBufferAmount,
+ {
+ slippageBufferAmount,
+ },
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -71,9 +70,10 @@ describe('marketUtils', () => {
const slippageBufferAmount = new BigNumber(5);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
- slippageBufferAmount,
+ {
+ slippageBufferAmount,
+ },
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5));
@@ -83,7 +83,6 @@ describe('marketUtils', () => {
const fillAmount = new BigNumber(10);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
@@ -94,7 +93,6 @@ describe('marketUtils', () => {
const fillAmount = new BigNumber(15);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
@@ -120,8 +118,10 @@ describe('marketUtils', () => {
const fillAmount = new BigNumber(30);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
+ {
+ remainingFillableMakerAssetAmounts,
+ },
);
expect(resultOrders).to.be.deep.equal([inputOrders[1], inputOrders[2]]);
expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(15));
@@ -137,15 +137,11 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableFeeAmounts that equal the zrxAmount
- const remainingFillableFeeAmounts = [zrxAmount, zrxAmount, zrxAmount];
describe('no target orders', () => {
it('returns empty and zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
[],
- [],
inputFeeOrders,
- remainingFillableFeeAmounts,
);
expect(resultOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -168,9 +164,10 @@ describe('marketUtils', () => {
it('returns empty and non-zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
- [],
[],
+ {
+ remainingFillableMakerAssetAmounts,
+ },
);
expect(resultOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
@@ -185,14 +182,10 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
- const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns empty and zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
inputFeeOrders,
- remainingFillableFeeAmounts,
);
expect(resultOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -210,14 +203,10 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
- const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns input fee orders and zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
inputFeeOrders,
- remainingFillableFeeAmounts,
);
expect(resultOrders).to.be.deep.equal(inputFeeOrders);
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -243,9 +232,10 @@ describe('marketUtils', () => {
it('returns first two input fee orders and zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
inputFeeOrders,
- remainingFillableFeeAmounts,
+ {
+ remainingFillableMakerAssetAmounts,
+ },
);
expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]);
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -263,14 +253,10 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
- const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns input fee orders and non-zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
inputFeeOrders,
- remainingFillableFeeAmounts,
);
expect(resultOrders).to.be.deep.equal(inputFeeOrders);
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
diff --git a/packages/order-utils/test/order_state_utils_test.ts b/packages/order-utils/test/order_state_utils_test.ts
new file mode 100644
index 000000000..91ef23b69
--- /dev/null
+++ b/packages/order-utils/test/order_state_utils_test.ts
@@ -0,0 +1,124 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { AbstractBalanceAndProxyAllowanceFetcher } from '../src/abstract/abstract_balance_and_proxy_allowance_fetcher';
+import { AbstractOrderFilledCancelledFetcher } from '../src/abstract/abstract_order_filled_cancelled_fetcher';
+import { OrderStateUtils } from '../src/order_state_utils';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrderFactory } from './utils/test_order_factory';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('OrderStateUtils', () => {
+ describe('#getOpenOrderStateAsync', () => {
+ const buildMockBalanceFetcher = (takerBalance: BigNumber): AbstractBalanceAndProxyAllowanceFetcher => {
+ const balanceFetcher = {
+ async getBalanceAsync(_assetData: string, _userAddress: string): Promise<BigNumber> {
+ return takerBalance;
+ },
+ async getProxyAllowanceAsync(_assetData: string, _userAddress: string): Promise<BigNumber> {
+ return takerBalance;
+ },
+ };
+ return balanceFetcher;
+ };
+ const buildMockOrderFilledFetcher = (
+ filledAmount: BigNumber = new BigNumber(0),
+ cancelled: boolean = false,
+ ): AbstractOrderFilledCancelledFetcher => {
+ const orderFetcher = {
+ async getFilledTakerAmountAsync(_orderHash: string): Promise<BigNumber> {
+ return filledAmount;
+ },
+ async isOrderCancelledAsync(_orderHash: string): Promise<boolean> {
+ return cancelled;
+ },
+ getZRXAssetData(): string {
+ return '';
+ },
+ };
+ return orderFetcher;
+ };
+ it('should have valid order state if order can be fully filled with small maker amount', async () => {
+ const makerAssetAmount = new BigNumber(10);
+ const takerAssetAmount = new BigNumber(10000000000000000);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = new BigNumber(0);
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
+ expect(orderState.isValid).to.eq(true);
+ });
+ it('should be invalid when an order is partially filled where only a rounding error remains', async () => {
+ const makerAssetAmount = new BigNumber(1001);
+ const takerAssetAmount = new BigNumber(3);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = new BigNumber(2);
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
+ expect(orderState.isValid).to.eq(false);
+ });
+ it('should be invalid when an order is cancelled', async () => {
+ const makerAssetAmount = new BigNumber(1000);
+ const takerAssetAmount = new BigNumber(2);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = new BigNumber(0);
+ const isCancelled = true;
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
+ expect(orderState.isValid).to.eq(false);
+ });
+ it('should be invalid when an order is fully filled', async () => {
+ const makerAssetAmount = new BigNumber(1000);
+ const takerAssetAmount = new BigNumber(2);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = takerAssetAmount;
+ const isCancelled = false;
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
+ expect(orderState.isValid).to.eq(false);
+ });
+ });
+});
diff --git a/packages/order-utils/test/rate_utils_test.ts b/packages/order-utils/test/rate_utils_test.ts
new file mode 100644
index 000000000..2e299c209
--- /dev/null
+++ b/packages/order-utils/test/rate_utils_test.ts
@@ -0,0 +1,55 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { rateUtils } from '../src';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrderFactory } from './utils/test_order_factory';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('rateUtils', () => {
+ const testOrder = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(100),
+ takerFee: new BigNumber(20),
+ });
+ describe('#getFeeAdjustedRateOfOrder', () => {
+ it('throws when feeRate is less than zero', async () => {
+ const feeRate = new BigNumber(-1);
+ expect(() => rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate)).to.throw(
+ 'Expected feeRate: -1 to be greater than or equal to 0',
+ );
+ });
+ it('correctly calculates fee adjusted rate when feeRate is provided', async () => {
+ const feeRate = new BigNumber(2); // ZRX costs 2 units of takerAsset per 1 unit of ZRX
+ const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate);
+ // the order actually takes 100 + (2 * 20) takerAsset units to fill 100 units of makerAsset
+ expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1.4));
+ });
+ it('correctly calculates fee adjusted rate when no feeRate is provided', async () => {
+ const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfOrder(testOrder);
+ // because no feeRate was provided we just assume 0 fees
+ // the order actually takes 100 takerAsset units to fill 100 units of makerAsset
+ expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1));
+ });
+ });
+ describe('#getFeeAdjustedRateOfFeeOrder', () => {
+ it('throws when takerFee exceeds makerAssetAmount', async () => {
+ const badOrder = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerFee: new BigNumber(101),
+ });
+ expect(() => rateUtils.getFeeAdjustedRateOfFeeOrder(badOrder)).to.throw(
+ 'Expected takerFee: "101" to be less than makerAssetAmount: "100"',
+ );
+ });
+ it('correctly calculates fee adjusted rate', async () => {
+ const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfFeeOrder(testOrder);
+ // the order actually takes 100 takerAsset units to fill (100 - 20) units of makerAsset
+ expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1.25));
+ });
+ });
+});
diff --git a/packages/order-utils/test/sorting_utils_test.ts b/packages/order-utils/test/sorting_utils_test.ts
new file mode 100644
index 000000000..016432505
--- /dev/null
+++ b/packages/order-utils/test/sorting_utils_test.ts
@@ -0,0 +1,67 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { sortingUtils } from '../src';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrderFactory } from './utils/test_order_factory';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('sortingUtils', () => {
+ describe('#sortOrdersByFeeAdjustedRate', () => {
+ const feeRate = new BigNumber(1); // ZRX costs 1 unit of takerAsset per 1 unit of ZRX
+ // rate: 2 takerAsset / makerAsset
+ const testOrder1 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ });
+ // rate: 1 takerAsset / makerAsset
+ const testOrder2 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(100),
+ });
+ // rate: 2.5 takerAsset / makerAsset
+ const testOrder3 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ takerFee: new BigNumber(50),
+ });
+ it('correctly sorts by fee adjusted rate when feeRate is Provided', async () => {
+ const orders = [testOrder1, testOrder2, testOrder3];
+ const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders, feeRate);
+ expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]);
+ });
+ it('correctly sorts by fee adjusted rate when no feeRate is Provided', async () => {
+ const orders = [testOrder1, testOrder2, testOrder3];
+ const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders);
+ expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]);
+ });
+ });
+ describe('#sortFeeOrdersByFeeAdjustedRate', () => {
+ // rate: 200 takerAsset / makerAsset
+ const testOrder1 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ takerFee: new BigNumber(99),
+ });
+ // rate: 1 takerAsset / makerAsset
+ const testOrder2 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(100),
+ });
+ // rate: 4 takerAsset / makerAsset
+ const testOrder3 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ takerFee: new BigNumber(50),
+ });
+ it('correctly sorts by fee adjusted rate', async () => {
+ const orders = [testOrder1, testOrder2, testOrder3];
+ const sortedOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate(orders);
+ expect(sortedOrders).to.deep.equal([testOrder2, testOrder3, testOrder1]);
+ });
+ });
+});
diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json
index 5ce1805e7..59d80fd08 100644
--- a/packages/order-watcher/package.json
+++ b/packages/order-watcher/package.json
@@ -55,7 +55,7 @@
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"json-loader": "^0.5.4",
"make-promises-safe": "^1.1.0",
diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts
index 00962bed0..38bfde7ef 100644
--- a/packages/order-watcher/test/order_watcher_test.ts
+++ b/packages/order-watcher/test/order_watcher_test.ts
@@ -501,25 +501,27 @@ describe('OrderWatcher', () => {
expect(orderState.isValid).to.be.false();
const invalidOrderState = orderState as OrderStateInvalid;
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError);
+ expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderCancelled);
});
orderWatcher.subscribe(callback);
await contractWrappers.exchange.cancelOrderAsync(signedOrder);
})().catch(done);
});
- it('should emit orderStateInvalid when within rounding error range', (done: DoneCallback) => {
+ it('should emit orderStateInvalid when within rounding error range after a partial fill', (done: DoneCallback) => {
(async () => {
- const remainingFillableAmountInBaseUnits = new BigNumber(100);
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
+ const fillAmountInBaseUnits = new BigNumber(2);
+ const makerAssetAmount = new BigNumber(1001);
+ const takerAssetAmount = new BigNumber(3);
+ signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
makerAssetData,
takerAssetData,
makerAddress,
takerAddress,
- fillableAmount,
+ makerAssetAmount,
+ takerAssetAmount,
);
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
await orderWatcher.addOrderAsync(signedOrder);
-
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.false();
const invalidOrderState = orderState as OrderStateInvalid;
@@ -527,11 +529,7 @@ describe('OrderWatcher', () => {
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError);
});
orderWatcher.subscribe(callback);
- await contractWrappers.exchange.fillOrderAsync(
- signedOrder,
- fillableAmount.minus(remainingFillableAmountInBaseUnits),
- takerAddress,
- );
+ await contractWrappers.exchange.fillOrderAsync(signedOrder, fillAmountInBaseUnits, takerAddress);
})().catch(done);
});
describe('erc721', () => {
diff --git a/packages/react-docs-example/package.json b/packages/react-docs-example/package.json
index 001b354d7..8efe35089 100644
--- a/packages/react-docs-example/package.json
+++ b/packages/react-docs-example/package.json
@@ -34,7 +34,7 @@
"@types/react-dom": "^16.0.3",
"@types/react-tap-event-plugin": "0.0.30",
"awesome-typescript-loader": "^3.1.3",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"css-loader": "^0.28.9",
"json-loader": "^0.5.4",
"less": "^2.7.2",
diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json
index a530e526d..f09bb64a0 100644
--- a/packages/react-docs/package.json
+++ b/packages/react-docs/package.json
@@ -29,7 +29,7 @@
"@0xproject/monorepo-scripts": "^1.0.5",
"@0xproject/tslint-config": "^1.0.5",
"@types/compare-versions": "^3.0.0",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "^5.9.1",
diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json
index 6eaac9d07..83b4cc5c9 100644
--- a/packages/react-shared/package.json
+++ b/packages/react-shared/package.json
@@ -28,7 +28,7 @@
"@0xproject/dev-utils": "^1.0.4",
"@0xproject/monorepo-scripts": "^1.0.5",
"@0xproject/tslint-config": "^1.0.5",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "^5.9.1",
diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json
index 29b8f9f3a..6543b782b 100644
--- a/packages/sol-compiler/package.json
+++ b/packages/sol-compiler/package.json
@@ -61,7 +61,7 @@
"@types/semver": "^5.5.0",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json
index 1d98faf8b..bc24fd1dc 100644
--- a/packages/sol-cov/package.json
+++ b/packages/sol-cov/package.json
@@ -79,7 +79,7 @@
"@types/rimraf": "^2.0.2",
"@types/solidity-parser-antlr": "^0.2.1",
"chai": "^4.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json
index 46ad8f784..85d11e9e7 100644
--- a/packages/sol-resolver/package.json
+++ b/packages/sol-resolver/package.json
@@ -26,7 +26,7 @@
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.5",
"@0xproject/tslint-config": "^1.0.5",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "5.11.0",
diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json
index 175a4ca1b..8c213ee26 100644
--- a/packages/sra-report/package.json
+++ b/packages/sra-report/package.json
@@ -57,7 +57,7 @@
"@types/yargs": "^10.0.0",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json
index ab3ae1a5a..57b0a13b3 100644
--- a/packages/subproviders/package.json
+++ b/packages/subproviders/package.json
@@ -74,7 +74,7 @@
"@types/sinon": "^2.2.2",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json
index 6956a9105..c0a1977f9 100644
--- a/packages/tslint-config/package.json
+++ b/packages/tslint-config/package.json
@@ -36,7 +36,7 @@
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.5",
"@types/lodash": "4.14.104",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"typescript": "3.0.1"
diff --git a/packages/types/package.json b/packages/types/package.json
index 6a36b897b..a41f78aac 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -26,7 +26,7 @@
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.5",
"@0xproject/tslint-config": "^1.0.5",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "5.11.0",
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index fa634420d..04480d093 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -62,8 +62,7 @@ export interface ValidatorSignature {
export enum ExchangeContractErrs {
OrderFillExpired = 'ORDER_FILL_EXPIRED',
OrderCancelExpired = 'ORDER_CANCEL_EXPIRED',
- OrderCancelAmountZero = 'ORDER_CANCEL_AMOUNT_ZERO',
- OrderAlreadyCancelledOrFilled = 'ORDER_ALREADY_CANCELLED_OR_FILLED',
+ OrderCancelled = 'ORDER_CANCELLED',
OrderFillAmountZero = 'ORDER_FILL_AMOUNT_ZERO',
OrderRemainingFillAmountZero = 'ORDER_REMAINING_FILL_AMOUNT_ZERO',
OrderFillRoundingError = 'ORDER_FILL_ROUNDING_ERROR',
diff --git a/packages/typescript-typings/package.json b/packages/typescript-typings/package.json
index 01a1d8adc..5d9768cb0 100644
--- a/packages/typescript-typings/package.json
+++ b/packages/typescript-typings/package.json
@@ -33,7 +33,7 @@
},
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.5",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"shx": "^0.2.2"
},
"publishConfig": {
diff --git a/packages/utils/package.json b/packages/utils/package.json
index c596f0620..28a967a35 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -34,7 +34,7 @@
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"chai": "^4.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json
index 437a1c6b5..d672db7e4 100644
--- a/packages/web3-wrapper/package.json
+++ b/packages/web3-wrapper/package.json
@@ -51,7 +51,7 @@
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"ganache-core": "0xProject/ganache-core#monorepo-dep",
"make-promises-safe": "^1.1.0",
diff --git a/packages/website/package.json b/packages/website/package.json
index 0fcf9c9b9..3b4055856 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -84,7 +84,7 @@
"@types/redux": "^3.6.0",
"awesome-typescript-loader": "^3.1.3",
"copy-webpack-plugin": "^4.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"css-loader": "0.23.x",
"exports-loader": "0.6.x",
"imports-loader": "0.6.x",
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index 39bbd404c..32b07473c 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -247,12 +247,9 @@ export const utils = {
} = {
[ExchangeContractErrs.OrderFillExpired]: 'This order has expired',
[ExchangeContractErrs.OrderCancelExpired]: 'This order has expired',
- [ExchangeContractErrs.OrderCancelAmountZero]: "Order cancel amount can't be 0",
- [ExchangeContractErrs.OrderAlreadyCancelledOrFilled]:
- 'This order has already been completely filled or cancelled',
+ [ExchangeContractErrs.OrderCancelled]: 'This order has been cancelled',
[ExchangeContractErrs.OrderFillAmountZero]: "Order fill amount can't be 0",
- [ExchangeContractErrs.OrderRemainingFillAmountZero]:
- 'This order has already been completely filled or cancelled',
+ [ExchangeContractErrs.OrderRemainingFillAmountZero]: 'This order has already been completely filled',
[ExchangeContractErrs.OrderFillRoundingError]:
'Rounding error will occur when filling this order. Please try filling a different amount.',
[ExchangeContractErrs.InsufficientTakerBalance]: