From 32ab4dcac723e189ce8a1be796f0539975a48eae Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 15:52:30 -0400 Subject: Implement rate utils --- packages/order-utils/src/index.ts | 1 + packages/order-utils/src/rate_utils.ts | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 packages/order-utils/src/rate_utils.ts (limited to 'packages') diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index 858f500c6..a52f936b6 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -33,3 +33,4 @@ 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'; diff --git a/packages/order-utils/src/rate_utils.ts b/packages/order-utils/src/rate_utils.ts new file mode 100644 index 000000000..212431e0c --- /dev/null +++ b/packages/order-utils/src/rate_utils.ts @@ -0,0 +1,44 @@ +import { schemas } from '@0xproject/json-schemas'; +import { SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; + +import { assert } from './assert'; +import { constants } from './constants'; + +export const rateUtils = { + /** + * Takes a signed 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 signedOrder An object that conforms to the signedOrder 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) + * @return The rate (takerAsset/makerAsset) of the order adjusted for fees + */ + getFeeAdjustedRateOfOrder(signedOrder: SignedOrder, feeRate: BigNumber): BigNumber { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isBigNumber('feeRate', feeRate); + assert.assert(feeRate.greaterThan(constants.ZERO_AMOUNT), `Expected feeRate: ${feeRate} to be greater than 0`); + const takerAssetAmountNeededToPayForFees = signedOrder.takerFee.mul(feeRate); + const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(signedOrder.takerAssetAmount); + const rate = totalTakerAssetAmount.div(signedOrder.makerAssetAmount); + return rate; + }, + /** + * Takes a signed 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 signedFeeOrder An object that conforms to the signedOrder interface + * @return The rate (WETH/ZRX) of the fee order adjusted for fees + */ + getFeeAdjustedRateOfFeeOrder(signedFeeOrder: SignedOrder): BigNumber { + assert.doesConformToSchema('signedFeeOrder', signedFeeOrder, schemas.signedOrderSchema); + const zrxAmountAfterFees = signedFeeOrder.makerAssetAmount.sub(signedFeeOrder.takerFee); + assert.assert( + zrxAmountAfterFees.greaterThan(constants.ZERO_AMOUNT), + `Expected takerFee: ${JSON.stringify( + signedFeeOrder.takerFee, + )} to be less than makerAssetAmount: ${JSON.stringify(signedFeeOrder.makerAssetAmount)}`, + ); + const rate = signedFeeOrder.takerAssetAmount.div(zrxAmountAfterFees); + return rate; + }, +}; -- cgit v1.2.3 From a1860b076d9d3408e64d8ff5e6bc0657e9ff7e7b Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 17:24:08 -0400 Subject: Add tests for rateUtils --- packages/order-utils/test/rate_utils_test.ts | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 packages/order-utils/test/rate_utils_test.ts (limited to 'packages') 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..2f321a7db --- /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 { constants, 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 zero', async () => { + const feeRate = constants.ZERO_AMOUNT; + expect(() => rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate)).to.throw( + 'Expected feeRate: 0 to be greater than 0', + ); + }); + 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 0', + ); + }); + it('correctly calculates fee adjusted rate', 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)); + }); + }); + 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)); + }); + }); +}); -- cgit v1.2.3 From c0924d8067079f246c5cad32f7acb3d1f6cfd9b9 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 17:49:22 -0400 Subject: Implement sorting utils --- packages/order-utils/src/index.ts | 1 + packages/order-utils/src/sorting_utils.ts | 69 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 packages/order-utils/src/sorting_utils.ts (limited to 'packages') diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index a52f936b6..359954641 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -34,3 +34,4 @@ 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/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts new file mode 100644 index 000000000..7474a302f --- /dev/null +++ b/packages/order-utils/src/sorting_utils.ts @@ -0,0 +1,69 @@ +import { schemas } from '@0xproject/json-schemas'; +import { SignedOrder } 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 signed 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 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 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) + * @return The input orders sorted by rate in ascending order + */ + sortOrdersByFeeAdjustedRate(signedOrders: SignedOrder[], feeRate: BigNumber): SignedOrder[] { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isBigNumber('feeRate', feeRate); + assert.assert(feeRate.greaterThan(constants.ZERO_AMOUNT), `Expected feeRate: ${feeRate} to be greater than 0`); + const rateCalculator = (signedOrder: SignedOrder) => rateUtils.getFeeAdjustedRateOfOrder(signedOrder, feeRate); + const sortedOrders = sortOrders(signedOrders, rateCalculator); + return sortedOrders; + }, + /** + * Takes an array of signed 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 signedFeeOrders An array of objects that conform to the SignedOrder 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(signedFeeOrders: SignedOrder[]): SignedOrder[] { + assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + const rateCalculator = rateUtils.getFeeAdjustedRateOfFeeOrder; + const sortedOrders = sortOrders(signedFeeOrders, rateCalculator); + return sortedOrders; + }, +}; + +type RateCalculator = (signedOrder: SignedOrder) => BigNumber; + +// takes an array of orders, copies them, and sorts the copy based on the rate definition provided by rateCalculator +const sortOrders = (signedOrders: SignedOrder[], rateCalculator: RateCalculator): SignedOrder[] => { + const copiedOrders = _.cloneDeep(signedOrders); + const feeOrderComparator = getOrderComparator(rateCalculator); + copiedOrders.sort(feeOrderComparator); + return copiedOrders; +}; + +type Comparator = (first: T, second: T) => number; + +// takes a function that calculates rate for a signed order and returns a comparator that sorts based on rate +const getOrderComparator = (rateCalculator: RateCalculator): Comparator => ( + firstSignedOrder, + secondSignedOrder, +) => { + const firstOrderRate = rateCalculator(firstSignedOrder); + const secondOrderRate = rateCalculator(secondSignedOrder); + if (firstOrderRate.lt(secondOrderRate)) { + return -1; + } else if (firstOrderRate.gt(secondOrderRate)) { + return 1; + } else { + return 0; + } +}; -- cgit v1.2.3 From fcd57d2743e4b6a1363b8071696147a91d2afb00 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 18:43:31 -0400 Subject: Add tests for sortingUtils --- packages/order-utils/src/sorting_utils.ts | 1 - packages/order-utils/test/sorting_utils_test.ts | 66 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 packages/order-utils/test/sorting_utils_test.ts (limited to 'packages') diff --git a/packages/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts index 7474a302f..2acd8180f 100644 --- a/packages/order-utils/src/sorting_utils.ts +++ b/packages/order-utils/src/sorting_utils.ts @@ -20,7 +20,6 @@ export const sortingUtils = { sortOrdersByFeeAdjustedRate(signedOrders: SignedOrder[], feeRate: BigNumber): SignedOrder[] { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.isBigNumber('feeRate', feeRate); - assert.assert(feeRate.greaterThan(constants.ZERO_AMOUNT), `Expected feeRate: ${feeRate} to be greater than 0`); const rateCalculator = (signedOrder: SignedOrder) => rateUtils.getFeeAdjustedRateOfOrder(signedOrder, feeRate); const sortedOrders = sortOrders(signedOrders, rateCalculator); return sortedOrders; 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..efce13d3f --- /dev/null +++ b/packages/order-utils/test/sorting_utils_test.ts @@ -0,0 +1,66 @@ +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import * as _ from 'lodash'; +import 'mocha'; + +import { constants, rateUtils, 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', () => { + // 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', async () => { + const feeRate = new BigNumber(1); // ZRX costs 1 unit of takerAsset per 1 unit of ZRX + const orders = [testOrder1, testOrder2, testOrder3]; + const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate( + [testOrder1, testOrder2, testOrder3], + feeRate, + ); + 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([testOrder1, testOrder2, testOrder3]); + expect(sortedOrders).to.deep.equal([testOrder2, testOrder3, testOrder1]); + }); + }); +}); -- cgit v1.2.3 From cbe639866ec9d6088cc7aa133033d2735524c5a0 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 18:54:17 -0400 Subject: Make feeRate optional with a default of 0 --- packages/order-utils/src/rate_utils.ts | 9 +++++++-- packages/order-utils/src/sorting_utils.ts | 6 +++++- packages/order-utils/test/rate_utils_test.ts | 8 +------- 3 files changed, 13 insertions(+), 10 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/src/rate_utils.ts b/packages/order-utils/src/rate_utils.ts index 212431e0c..72d11584a 100644 --- a/packages/order-utils/src/rate_utils.ts +++ b/packages/order-utils/src/rate_utils.ts @@ -1,6 +1,7 @@ import { schemas } from '@0xproject/json-schemas'; import { SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import * as _ from 'lodash'; import { assert } from './assert'; import { constants } from './constants'; @@ -12,12 +13,16 @@ export const rateUtils = { * @param signedOrder An object that conforms to the signedOrder 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(signedOrder: SignedOrder, feeRate: BigNumber): BigNumber { + getFeeAdjustedRateOfOrder(signedOrder: SignedOrder, feeRate: BigNumber = constants.ZERO_AMOUNT): BigNumber { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isBigNumber('feeRate', feeRate); - assert.assert(feeRate.greaterThan(constants.ZERO_AMOUNT), `Expected feeRate: ${feeRate} to be greater than 0`); + assert.assert( + feeRate.gte(constants.ZERO_AMOUNT), + `Expected feeRate: ${feeRate} to be greater than or equal to 0`, + ); const takerAssetAmountNeededToPayForFees = signedOrder.takerFee.mul(feeRate); const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(signedOrder.takerAssetAmount); const rate = totalTakerAssetAmount.div(signedOrder.makerAssetAmount); diff --git a/packages/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts index 2acd8180f..8424060fc 100644 --- a/packages/order-utils/src/sorting_utils.ts +++ b/packages/order-utils/src/sorting_utils.ts @@ -15,9 +15,13 @@ export const sortingUtils = { * 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(signedOrders: SignedOrder[], feeRate: BigNumber): SignedOrder[] { + sortOrdersByFeeAdjustedRate( + signedOrders: SignedOrder[], + feeRate: BigNumber = constants.ZERO_AMOUNT, + ): SignedOrder[] { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.isBigNumber('feeRate', feeRate); const rateCalculator = (signedOrder: SignedOrder) => rateUtils.getFeeAdjustedRateOfOrder(signedOrder, feeRate); diff --git a/packages/order-utils/test/rate_utils_test.ts b/packages/order-utils/test/rate_utils_test.ts index 2f321a7db..167a40465 100644 --- a/packages/order-utils/test/rate_utils_test.ts +++ b/packages/order-utils/test/rate_utils_test.ts @@ -17,16 +17,10 @@ describe('rateUtils', () => { takerFee: new BigNumber(20), }); describe('#getFeeAdjustedRateOfOrder', () => { - it('throws when feeRate is zero', async () => { - const feeRate = constants.ZERO_AMOUNT; - expect(() => rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate)).to.throw( - 'Expected feeRate: 0 to be greater than 0', - ); - }); 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 0', + 'Expected feeRate: -1 to be greater than or equal to 0', ); }); it('correctly calculates fee adjusted rate', async () => { -- cgit v1.2.3 From af52598d320462357d3ce40d37cf7de9a4f054ee Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 18:59:29 -0400 Subject: Update tests for optional feeRate --- packages/order-utils/test/rate_utils_test.ts | 8 +++++++- packages/order-utils/test/sorting_utils_test.ts | 9 +++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/test/rate_utils_test.ts b/packages/order-utils/test/rate_utils_test.ts index 167a40465..b23a6467a 100644 --- a/packages/order-utils/test/rate_utils_test.ts +++ b/packages/order-utils/test/rate_utils_test.ts @@ -23,12 +23,18 @@ describe('rateUtils', () => { 'Expected feeRate: -1 to be greater than or equal to 0', ); }); - it('correctly calculates fee adjusted rate', async () => { + 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 () => { diff --git a/packages/order-utils/test/sorting_utils_test.ts b/packages/order-utils/test/sorting_utils_test.ts index efce13d3f..5a33cb2ca 100644 --- a/packages/order-utils/test/sorting_utils_test.ts +++ b/packages/order-utils/test/sorting_utils_test.ts @@ -13,6 +13,7 @@ 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), @@ -29,8 +30,7 @@ describe('sortingUtils', () => { takerAssetAmount: new BigNumber(200), takerFee: new BigNumber(50), }); - it('correctly sorts by fee adjusted rate', async () => { - const feeRate = new BigNumber(1); // ZRX costs 1 unit of takerAsset per 1 unit of ZRX + it('correctly sorts by fee adjusted rate when feeRate is Provided', async () => { const orders = [testOrder1, testOrder2, testOrder3]; const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate( [testOrder1, testOrder2, testOrder3], @@ -38,6 +38,11 @@ describe('sortingUtils', () => { ); 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([testOrder1, testOrder2, testOrder3]); + expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]); + }); }); describe('#sortFeeOrdersByFeeAdjustedRate', () => { // rate: 200 takerAsset / makerAsset -- cgit v1.2.3 From b86210332f94ad90cdabcf2083ae4a99075daf33 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 19:10:57 -0400 Subject: Fix lint errors --- packages/order-utils/src/rate_utils.ts | 1 - packages/order-utils/src/sorting_utils.ts | 2 +- packages/order-utils/test/rate_utils_test.ts | 2 +- packages/order-utils/test/sorting_utils_test.ts | 12 ++++-------- 4 files changed, 6 insertions(+), 11 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/src/rate_utils.ts b/packages/order-utils/src/rate_utils.ts index 72d11584a..e82c03873 100644 --- a/packages/order-utils/src/rate_utils.ts +++ b/packages/order-utils/src/rate_utils.ts @@ -1,7 +1,6 @@ import { schemas } from '@0xproject/json-schemas'; import { SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; -import * as _ from 'lodash'; import { assert } from './assert'; import { constants } from './constants'; diff --git a/packages/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts index 8424060fc..f019aa4a8 100644 --- a/packages/order-utils/src/sorting_utils.ts +++ b/packages/order-utils/src/sorting_utils.ts @@ -37,7 +37,7 @@ export const sortingUtils = { */ sortFeeOrdersByFeeAdjustedRate(signedFeeOrders: SignedOrder[]): SignedOrder[] { assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); - const rateCalculator = rateUtils.getFeeAdjustedRateOfFeeOrder; + const rateCalculator = rateUtils.getFeeAdjustedRateOfFeeOrder.bind(rateUtils); const sortedOrders = sortOrders(signedFeeOrders, rateCalculator); return sortedOrders; }, diff --git a/packages/order-utils/test/rate_utils_test.ts b/packages/order-utils/test/rate_utils_test.ts index b23a6467a..2e299c209 100644 --- a/packages/order-utils/test/rate_utils_test.ts +++ b/packages/order-utils/test/rate_utils_test.ts @@ -2,7 +2,7 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import 'mocha'; -import { constants, rateUtils } from '../src'; +import { rateUtils } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { testOrderFactory } from './utils/test_order_factory'; diff --git a/packages/order-utils/test/sorting_utils_test.ts b/packages/order-utils/test/sorting_utils_test.ts index 5a33cb2ca..016432505 100644 --- a/packages/order-utils/test/sorting_utils_test.ts +++ b/packages/order-utils/test/sorting_utils_test.ts @@ -1,9 +1,8 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; -import * as _ from 'lodash'; import 'mocha'; -import { constants, rateUtils, sortingUtils } from '../src'; +import { sortingUtils } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { testOrderFactory } from './utils/test_order_factory'; @@ -32,15 +31,12 @@ describe('sortingUtils', () => { }); it('correctly sorts by fee adjusted rate when feeRate is Provided', async () => { const orders = [testOrder1, testOrder2, testOrder3]; - const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate( - [testOrder1, testOrder2, testOrder3], - feeRate, - ); + 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([testOrder1, testOrder2, testOrder3]); + const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders); expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]); }); }); @@ -64,7 +60,7 @@ describe('sortingUtils', () => { }); it('correctly sorts by fee adjusted rate', async () => { const orders = [testOrder1, testOrder2, testOrder3]; - const sortedOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate([testOrder1, testOrder2, testOrder3]); + const sortedOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate(orders); expect(sortedOrders).to.deep.equal([testOrder2, testOrder3, testOrder1]); }); }); -- cgit v1.2.3 From ab64ea7377b4cd0a0a7e3ec219f958037c5fabbe Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 19:20:07 -0400 Subject: Updated CHANGELOG --- packages/order-utils/CHANGELOG.json | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages') diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index fa82976ad..ee0030b6b 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -13,6 +13,10 @@ }, { "note": "Dependencies updated" + }, + { + "note": "Added rateUtils and sortingUtils", + "pr": 953 } ] }, -- cgit v1.2.3 From d8593998414aa3234533b8fa868b05495ac54457 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 13 Aug 2018 17:45:50 -0700 Subject: Change rateUtils to use Order --- packages/order-utils/src/rate_utils.ts | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/src/rate_utils.ts b/packages/order-utils/src/rate_utils.ts index e82c03873..c9ca72c59 100644 --- a/packages/order-utils/src/rate_utils.ts +++ b/packages/order-utils/src/rate_utils.ts @@ -1,5 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; -import { SignedOrder } from '@0xproject/types'; +import { Order } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { assert } from './assert'; @@ -7,42 +7,42 @@ import { constants } from './constants'; export const rateUtils = { /** - * Takes a signed order and calculates the fee adjusted rate (takerAsset/makerAsset) by calculating how much takerAsset + * 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 signedOrder An object that conforms to the signedOrder 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 + * @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(signedOrder: SignedOrder, feeRate: BigNumber = constants.ZERO_AMOUNT): BigNumber { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + 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 = signedOrder.takerFee.mul(feeRate); - const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(signedOrder.takerAssetAmount); - const rate = totalTakerAssetAmount.div(signedOrder.makerAssetAmount); + const takerAssetAmountNeededToPayForFees = order.takerFee.mul(feeRate); + const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(order.takerAssetAmount); + const rate = totalTakerAssetAmount.div(order.makerAssetAmount); return rate; }, /** - * Takes a signed fee order (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) and calculates + * 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 signedFeeOrder An object that conforms to the signedOrder interface + * @param feeOrder An object that conforms to the order interface * @return The rate (WETH/ZRX) of the fee order adjusted for fees */ - getFeeAdjustedRateOfFeeOrder(signedFeeOrder: SignedOrder): BigNumber { - assert.doesConformToSchema('signedFeeOrder', signedFeeOrder, schemas.signedOrderSchema); - const zrxAmountAfterFees = signedFeeOrder.makerAssetAmount.sub(signedFeeOrder.takerFee); + 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( - signedFeeOrder.takerFee, - )} to be less than makerAssetAmount: ${JSON.stringify(signedFeeOrder.makerAssetAmount)}`, + `Expected takerFee: ${JSON.stringify(feeOrder.takerFee)} to be less than makerAssetAmount: ${JSON.stringify( + feeOrder.makerAssetAmount, + )}`, ); - const rate = signedFeeOrder.takerAssetAmount.div(zrxAmountAfterFees); + const rate = feeOrder.takerAssetAmount.div(zrxAmountAfterFees); return rate; }, }; -- cgit v1.2.3 From 99b744ba52f538752bb0966e6d8b50d9f5a2f032 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 13 Aug 2018 18:31:41 -0700 Subject: Update sortingUtils to support Order and SignedOrder --- packages/order-utils/src/sorting_utils.ts | 70 ++++++++++++------------------- 1 file changed, 26 insertions(+), 44 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts index f019aa4a8..8811bcaf8 100644 --- a/packages/order-utils/src/sorting_utils.ts +++ b/packages/order-utils/src/sorting_utils.ts @@ -1,5 +1,5 @@ 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'; @@ -9,64 +9,46 @@ import { rateUtils } from './rate_utils'; export const sortingUtils = { /** - * Takes an array of signed orders and sorts them by takerAsset/makerAsset rate in ascending order (best rate first). + * 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 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 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 + * @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( - signedOrders: SignedOrder[], - feeRate: BigNumber = constants.ZERO_AMOUNT, - ): SignedOrder[] { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + sortOrdersByFeeAdjustedRate(orders: T[], feeRate: BigNumber = constants.ZERO_AMOUNT): T[] { + assert.doesConformToSchema('orders', orders, schemas.ordersSchema); assert.isBigNumber('feeRate', feeRate); - const rateCalculator = (signedOrder: SignedOrder) => rateUtils.getFeeAdjustedRateOfOrder(signedOrder, feeRate); - const sortedOrders = sortOrders(signedOrders, rateCalculator); + const rateCalculator = (order: Order) => rateUtils.getFeeAdjustedRateOfOrder(order, feeRate); + const sortedOrders = sortOrders(orders, rateCalculator); return sortedOrders; }, /** - * Takes an array of signed fee orders (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) + * 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 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 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(signedFeeOrders: SignedOrder[]): SignedOrder[] { - assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + sortFeeOrdersByFeeAdjustedRate(feeOrders: Order[]): Order[] { + assert.doesConformToSchema('feeOrders', feeOrders, schemas.ordersSchema); const rateCalculator = rateUtils.getFeeAdjustedRateOfFeeOrder.bind(rateUtils); - const sortedOrders = sortOrders(signedFeeOrders, rateCalculator); + const sortedOrders = sortOrders(feeOrders, rateCalculator); return sortedOrders; }, }; -type RateCalculator = (signedOrder: SignedOrder) => BigNumber; +type RateCalculator = (order: Order) => BigNumber; // takes an array of orders, copies them, and sorts the copy based on the rate definition provided by rateCalculator -const sortOrders = (signedOrders: SignedOrder[], rateCalculator: RateCalculator): SignedOrder[] => { - const copiedOrders = _.cloneDeep(signedOrders); - const feeOrderComparator = getOrderComparator(rateCalculator); - copiedOrders.sort(feeOrderComparator); +function sortOrders(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; -}; - -type Comparator = (first: T, second: T) => number; - -// takes a function that calculates rate for a signed order and returns a comparator that sorts based on rate -const getOrderComparator = (rateCalculator: RateCalculator): Comparator => ( - firstSignedOrder, - secondSignedOrder, -) => { - const firstOrderRate = rateCalculator(firstSignedOrder); - const secondOrderRate = rateCalculator(secondSignedOrder); - if (firstOrderRate.lt(secondOrderRate)) { - return -1; - } else if (firstOrderRate.gt(secondOrderRate)) { - return 1; - } else { - return 0; - } -}; +} -- cgit v1.2.3 From c10c4cec1db2c5bc0b71177aea7590ee6fda8735 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 21:14:46 -0400 Subject: Update marketUtils api --- packages/order-utils/src/market_utils.ts | 93 +++++++++++++++----------- packages/order-utils/src/types.ts | 28 ++++++++ packages/order-utils/test/market_utils_test.ts | 67 ++++++++++++------- 3 files changed, 125 insertions(+), 63 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts index 681059ddf..58e9ab7ba 100644 --- a/packages/order-utils/src/market_utils.ts +++ b/packages/order-utils/src/market_utils.ts @@ -5,37 +5,42 @@ 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 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 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[], makerAssetFillAmount: BigNumber, - slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, + opts?: FindOrdersThatCoverMakerAssetFillAmountOpts, ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount); + // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders + const remainingFillableMakerAssetAmounts = _.get( + opts, + 'remainingFillableMakerAssetAmounts', + _.map(signedOrders, 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', + 'Expected signedOrders.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 @@ -64,47 +69,53 @@ export const marketUtils = { 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 signedOrders 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 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 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 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, + opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts, ): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders + const remainingFillableMakerAssetAmounts = _.get( + opts, + 'remainingFillableMakerAssetAmounts', + _.map(signedOrders, order => order.makerAssetAmount), + ) as BigNumber[]; _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), ); - assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); - _.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', + 'Expected signedOrders.length to equal opts.remainingFillableMakerAssetAmounts.length', + ); + // try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from signedFeeOrders + const remainingFillableFeeAmounts = _.get( + opts, + 'remainingFillableFeeAmounts', + _.map(signedFeeOrders, order => order.makerAssetAmount), + ) as BigNumber[]; + _.forEach(remainingFillableFeeAmounts, (amount, index) => + assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), ); assert.assert( signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedFeeOrders.length to equal remainingFillableFeeAmounts.length', + 'Expected signedFeeOrders.length to equal opts.remainingFillableFeeAmounts.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 ZRX needed to fill signedOrders const totalFeeAmount = _.reduce( signedOrders, @@ -119,9 +130,11 @@ export const marketUtils = { ); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( signedFeeOrders, - remainingFillableFeeAmounts, totalFeeAmount, - slippageBufferAmount, + { + remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts, + slippageBufferAmount, + }, ); return { resultOrders, diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts index 1fbd8cf7b..8a9a4cafe 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 `signedOrders` parameter. + * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values. + * Defaults to `makerAssetAmount` values from the signedOrders 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 `signedOrders` parameter. + * You can use `OrderStateUtils` `@0xproject/order-utils` to perform blockchain lookups for these values. + * Defaults to `makerAssetAmount` values from the signedOrders 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. + * Defaults to `makerAssetAmount` values from the signedFeeOrders 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..2f6bb7bd1 100644 --- a/packages/order-utils/test/market_utils_test.ts +++ b/packages/order-utils/test/market_utils_test.ts @@ -11,13 +11,12 @@ chaiSetup.configure(); const expect = chai.expect; // tslint:disable: no-unused-expression -describe('marketUtils', () => { +describe.only('marketUtils', () => { describe('#findOrdersThatCoverMakerAssetFillAmount', () => { describe('no orders', () => { it('returns empty and unchanged remainingFillAmount', async () => { const fillAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - [], [], fillAmount, ); @@ -43,9 +42,11 @@ describe('marketUtils', () => { const slippageBufferAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, - slippageBufferAmount, + { + remainingFillableMakerAssetAmounts, + slippageBufferAmount, + }, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -57,9 +58,11 @@ describe('marketUtils', () => { const slippageBufferAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, - slippageBufferAmount, + { + remainingFillableMakerAssetAmounts, + slippageBufferAmount, + }, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -71,9 +74,11 @@ describe('marketUtils', () => { const slippageBufferAmount = new BigNumber(5); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, - slippageBufferAmount, + { + remainingFillableMakerAssetAmounts, + slippageBufferAmount, + }, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5)); @@ -83,8 +88,10 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, + { + remainingFillableMakerAssetAmounts, + }, ); expect(resultOrders).to.be.deep.equal([inputOrders[0]]); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -94,8 +101,10 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(15); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - remainingFillableMakerAssetAmounts, fillAmount, + { + remainingFillableMakerAssetAmounts, + }, ); expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -120,8 +129,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)); @@ -142,10 +153,11 @@ describe('marketUtils', () => { describe('no target orders', () => { it('returns empty and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( - [], [], inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.empty; expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -168,9 +180,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)); @@ -190,9 +203,11 @@ describe('marketUtils', () => { it('returns empty and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableMakerAssetAmounts, + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.empty; expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -215,9 +230,11 @@ describe('marketUtils', () => { it('returns input fee orders and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableMakerAssetAmounts, + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.deep.equal(inputFeeOrders); expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -243,9 +260,11 @@ describe('marketUtils', () => { it('returns first two input fee orders and zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableMakerAssetAmounts, + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]); expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -268,9 +287,11 @@ describe('marketUtils', () => { it('returns input fee orders and non-zero remainingFeeAmount', async () => { const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( inputOrders, - remainingFillableMakerAssetAmounts, inputFeeOrders, - remainingFillableFeeAmounts, + { + remainingFillableMakerAssetAmounts, + remainingFillableFeeAmounts, + }, ); expect(resultOrders).to.be.deep.equal(inputFeeOrders); expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); -- cgit v1.2.3 From 66745c5260d2e2802211697980ce91a0cf084e83 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 21:18:13 -0400 Subject: Remove remaining amounts that are now defaults in tests --- packages/order-utils/test/market_utils_test.ts | 37 +------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts index 2f6bb7bd1..109420a02 100644 --- a/packages/order-utils/test/market_utils_test.ts +++ b/packages/order-utils/test/market_utils_test.ts @@ -11,7 +11,7 @@ chaiSetup.configure(); const expect = chai.expect; // tslint:disable: no-unused-expression -describe.only('marketUtils', () => { +describe('marketUtils', () => { describe('#findOrdersThatCoverMakerAssetFillAmount', () => { describe('no orders', () => { it('returns empty and unchanged remainingFillAmount', async () => { @@ -33,8 +33,6 @@ describe.only('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 @@ -44,7 +42,6 @@ describe.only('marketUtils', () => { inputOrders, fillAmount, { - remainingFillableMakerAssetAmounts, slippageBufferAmount, }, ); @@ -60,7 +57,6 @@ describe.only('marketUtils', () => { inputOrders, fillAmount, { - remainingFillableMakerAssetAmounts, slippageBufferAmount, }, ); @@ -76,7 +72,6 @@ describe.only('marketUtils', () => { inputOrders, fillAmount, { - remainingFillableMakerAssetAmounts, slippageBufferAmount, }, ); @@ -89,9 +84,6 @@ describe.only('marketUtils', () => { const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, fillAmount, - { - remainingFillableMakerAssetAmounts, - }, ); expect(resultOrders).to.be.deep.equal([inputOrders[0]]); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -102,9 +94,6 @@ describe.only('marketUtils', () => { const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, fillAmount, - { - remainingFillableMakerAssetAmounts, - }, ); expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -148,16 +137,11 @@ describe.only('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); @@ -198,16 +182,10 @@ describe.only('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, inputFeeOrders, - { - remainingFillableMakerAssetAmounts, - remainingFillableFeeAmounts, - }, ); expect(resultOrders).to.be.empty; expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -225,16 +203,10 @@ describe.only('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, inputFeeOrders, - { - remainingFillableMakerAssetAmounts, - remainingFillableFeeAmounts, - }, ); expect(resultOrders).to.be.deep.equal(inputFeeOrders); expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); @@ -263,7 +235,6 @@ describe.only('marketUtils', () => { inputFeeOrders, { remainingFillableMakerAssetAmounts, - remainingFillableFeeAmounts, }, ); expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]); @@ -282,16 +253,10 @@ describe.only('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, inputFeeOrders, - { - remainingFillableMakerAssetAmounts, - remainingFillableFeeAmounts, - }, ); expect(resultOrders).to.be.deep.equal(inputFeeOrders); expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); -- cgit v1.2.3 From a2192e62df56efd95a0e3540296cd17a23cb2033 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 9 Aug 2018 21:26:45 -0400 Subject: Update CHANGELOG --- packages/order-utils/CHANGELOG.json | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'packages') diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index a81eb077d..7cefc1670 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -18,6 +18,11 @@ }, { "note": "Dependencies updated" + }, + { + "note": + "Update marketUtils api such that all optional parameters are bundled into one optional param and more defaults are provided", + "pr": 954 } ], "timestamp": 1534210131 -- cgit v1.2.3 From 6a2634d362e50e5a611f388c0785df3209cee308 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 13 Aug 2018 21:29:35 -0700 Subject: Make marketUtils interface compatible with Order and SignedOrder --- packages/order-utils/src/market_utils.ts | 72 ++++++++++++++++---------------- packages/order-utils/src/types.ts | 12 +++--- 2 files changed, 42 insertions(+), 42 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts index 58e9ab7ba..a0a827546 100644 --- a/packages/order-utils/src/market_utils.ts +++ b/packages/order-utils/src/market_utils.ts @@ -1,5 +1,5 @@ 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'; @@ -12,40 +12,40 @@ export const marketUtils = { * 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. + * @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[], + findOrdersThatCoverMakerAssetFillAmount( + orders: T[], makerAssetFillAmount: BigNumber, opts?: FindOrdersThatCoverMakerAssetFillAmountOpts, - ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + ): { 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 signedOrders + // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders const remainingFillableMakerAssetAmounts = _.get( opts, 'remainingFillableMakerAssetAmounts', - _.map(signedOrders, order => order.makerAssetAmount), + _.map(orders, order => order.makerAssetAmount), ) as BigNumber[]; _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), ); assert.assert( - signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedOrders.length to equal opts.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 }; @@ -64,61 +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 - * in order to fill the takerFees required by signedOrders plus a slippageBufferAmount. + * 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 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 opts Optional arguments this function accepts. + * @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[], - signedFeeOrders: SignedOrder[], + findFeeOrdersThatCoverFeesForTargetOrders( + orders: T[], + feeOrders: T[], opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts, - ): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); - // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from signedOrders + ): { 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(signedOrders, order => order.makerAssetAmount), + _.map(orders, order => order.makerAssetAmount), ) as BigNumber[]; _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), ); assert.assert( - signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedOrders.length to equal opts.remainingFillableMakerAssetAmounts.length', + 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 signedFeeOrders + // try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from feeOrders const remainingFillableFeeAmounts = _.get( opts, 'remainingFillableFeeAmounts', - _.map(signedFeeOrders, order => order.makerAssetAmount), + _.map(feeOrders, order => order.makerAssetAmount), ) as BigNumber[]; _.forEach(remainingFillableFeeAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), ); assert.assert( - signedOrders.length === remainingFillableMakerAssetAmounts.length, - 'Expected signedFeeOrders.length to equal opts.remainingFillableFeeAmounts.length', + feeOrders.length === remainingFillableFeeAmounts.length, + 'Expected feeOrders.length to equal opts.remainingFillableFeeAmounts.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 ZRX needed to fill signedOrders + // calculate total amount of ZRX needed to fill orders const totalFeeAmount = _.reduce( - signedOrders, + orders, (accFees, order, index) => { const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index]; const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable @@ -129,7 +129,7 @@ export const marketUtils = { constants.ZERO_AMOUNT, ); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - signedFeeOrders, + feeOrders, totalFeeAmount, { remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts, diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts index 8a9a4cafe..2e9c79d80 100644 --- a/packages/order-utils/src/types.ts +++ b/packages/order-utils/src/types.ts @@ -43,9 +43,9 @@ export interface CreateOrderOpts { } /** - * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `signedOrders` parameter. + * 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 signedOrders param. + * 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 */ @@ -55,12 +55,12 @@ export interface FindOrdersThatCoverMakerAssetFillAmountOpts { } /** - * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `signedOrders` parameter. + * 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 signedOrders param. - * remainingFillableFeeAmounts: An array of BigNumbers corresponding to the signedFeeOrders parameter. + * 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 signedFeeOrders param. + * 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 */ -- cgit v1.2.3 From db20ad1c5db5677b7d5ad54bf76a928b5857fe8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 14 Aug 2018 06:21:07 +0000 Subject: Bump @types/fetch-mock from 5.12.2 to 6.0.3 Bumps [@types/fetch-mock](https://github.com/DefinitelyTyped/DefinitelyTyped) from 5.12.2 to 6.0.3. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits) Signed-off-by: dependabot[bot] --- packages/connect/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/connect/package.json b/packages/connect/package.json index 1cc5e1bab..0fad3e14c 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", -- cgit v1.2.3 From 6baa5ef311112941ccaec3fb8a877dd57b63627b Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Mon, 13 Aug 2018 12:46:43 -0700 Subject: feat: Upgrade TypeScript to 3.0.1 --- packages/0x.js/package.json | 2 +- packages/abi-gen/package.json | 2 +- packages/assert/package.json | 2 +- packages/base-contract/package.json | 2 +- packages/connect/package.json | 2 +- packages/contract-wrappers/package.json | 2 +- packages/contracts/package.json | 2 +- packages/dev-utils/package.json | 2 +- packages/ethereum-types/package.json | 2 +- packages/fill-scenarios/package.json | 2 +- packages/json-schemas/package.json | 2 +- packages/metacoin/package.json | 2 +- packages/migrations/package.json | 2 +- packages/monorepo-scripts/package.json | 2 +- packages/order-utils/package.json | 2 +- packages/order-watcher/package.json | 2 +- packages/react-docs-example/package.json | 2 +- packages/react-docs/package.json | 2 +- packages/react-shared/package.json | 2 +- packages/sol-compiler/package.json | 2 +- packages/sol-cov/package.json | 2 +- packages/sol-resolver/package.json | 2 +- packages/sra-report/package.json | 2 +- packages/subproviders/package.json | 2 +- packages/testnet-faucets/package.json | 2 +- packages/tslint-config/package.json | 2 +- packages/types/package.json | 2 +- packages/utils/package.json | 2 +- packages/web3-wrapper/package.json | 2 +- packages/website/package.json | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) (limited to 'packages') diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index cf7b1962f..2daf40b54 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -94,7 +94,7 @@ "source-map-support": "^0.5.0", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2", + "typescript": "3.0.1", "webpack": "^3.1.0" }, "dependencies": { diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 8ea055a15..565fe4058 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -63,7 +63,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/assert/package.json b/packages/assert/package.json index 9d2669955..d249b4cd1 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -44,7 +44,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/json-schemas": "^1.0.1-rc.4", diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index e658d9cfa..c5375ecf6 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -40,7 +40,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/typescript-typings": "^1.0.4", diff --git a/packages/connect/package.json b/packages/connect/package.json index 1cc5e1bab..4ab5cec64 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -83,7 +83,7 @@ "shx": "^0.2.2", "tslint": "5.11.0", "typedoc": "~0.8.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index 7667b5b7f..ae2867e6c 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -68,7 +68,7 @@ "sinon": "^4.0.0", "source-map-support": "^0.5.0", "tslint": "5.11.0", - "typescript": "2.9.2", + "typescript": "3.0.1", "web3-provider-engine": "14.0.6" }, "dependencies": { diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 799f72d9e..01858894b 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -68,7 +68,7 @@ "solc": "^0.4.24", "solhint": "^1.2.1", "tslint": "5.11.0", - "typescript": "2.9.2", + "typescript": "3.0.1", "yargs": "^10.0.3" }, "dependencies": { diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 5aa6edcd8..544ff23fa 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -42,7 +42,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/subproviders": "^1.0.5", diff --git a/packages/ethereum-types/package.json b/packages/ethereum-types/package.json index 0e89a8049..c2092a1d3 100644 --- a/packages/ethereum-types/package.json +++ b/packages/ethereum-types/package.json @@ -41,7 +41,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@types/node": "^8.0.53", diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json index c3e8afb0e..466e96258 100644 --- a/packages/fill-scenarios/package.json +++ b/packages/fill-scenarios/package.json @@ -38,7 +38,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/base-contract": "^2.0.0-rc.1", diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index 40cb71c18..a5941a971 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -70,7 +70,7 @@ "shx": "^0.2.2", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index 6900da198..322708b50 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -56,6 +56,6 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" } } diff --git a/packages/migrations/package.json b/packages/migrations/package.json index d496393f7..dc481a972 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -49,7 +49,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2", + "typescript": "3.0.1", "yargs": "^10.0.3" }, "dependencies": { diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json index 4d92ed495..87135fd93 100644 --- a/packages/monorepo-scripts/package.json +++ b/packages/monorepo-scripts/package.json @@ -40,7 +40,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@lerna/batch-packages": "^3.0.0-beta.18", diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index fa8f3563e..bedbdc6d2 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -70,7 +70,7 @@ "sinon": "^4.0.0", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/assert": "^1.0.5", diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index ba4fed358..5ce1805e7 100644 --- a/packages/order-watcher/package.json +++ b/packages/order-watcher/package.json @@ -67,7 +67,7 @@ "sinon": "^4.0.0", "source-map-support": "^0.5.0", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/assert": "^1.0.5", diff --git a/packages/react-docs-example/package.json b/packages/react-docs-example/package.json index 1701e6adb..001b354d7 100644 --- a/packages/react-docs-example/package.json +++ b/packages/react-docs-example/package.json @@ -45,7 +45,7 @@ "source-map-loader": "^0.2.3", "style-loader": "^0.20.2", "tslint": "^5.9.1", - "typescript": "2.9.2", + "typescript": "3.0.1", "webpack": "^3.11.0", "webpack-dev-server": "^2.11.1" }, diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index e24ed8e6f..a530e526d 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -33,7 +33,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "^5.9.1", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/react-shared": "^1.0.6", diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json index 9761c246e..6eaac9d07 100644 --- a/packages/react-shared/package.json +++ b/packages/react-shared/package.json @@ -32,7 +32,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "^5.9.1", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@types/is-mobile": "0.3.0", diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json index 7cb07e970..29b8f9f3a 100644 --- a/packages/sol-compiler/package.json +++ b/packages/sol-compiler/package.json @@ -71,7 +71,7 @@ "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "types-bn": "^0.0.1", - "typescript": "2.9.2", + "typescript": "3.0.1", "web3-typescript-typings": "^0.10.2", "zeppelin-solidity": "1.8.0" }, diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index 4c3000360..1d98faf8b 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -89,7 +89,7 @@ "sinon": "^4.0.0", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json index 7a3c7509a..46ad8f784 100644 --- a/packages/sol-resolver/package.json +++ b/packages/sol-resolver/package.json @@ -30,7 +30,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/types": "^1.0.1-rc.4", diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json index 42321359c..175a4ca1b 100644 --- a/packages/sra-report/package.json +++ b/packages/sra-report/package.json @@ -66,7 +66,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 405b89db3..ab3ae1a5a 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -84,7 +84,7 @@ "sinon": "^4.0.0", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2", + "typescript": "3.0.1", "webpack": "^3.1.0" }, "optionalDependencies": { diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json index ce2a1a52d..769fdf371 100644 --- a/packages/testnet-faucets/package.json +++ b/packages/testnet-faucets/package.json @@ -43,7 +43,7 @@ "shx": "^0.2.2", "source-map-loader": "^0.1.6", "tslint": "5.11.0", - "typescript": "2.9.2", + "typescript": "3.0.1", "webpack": "^3.1.0", "webpack-node-externals": "^1.6.0" } diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index 1cc778caf..6956a9105 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -39,7 +39,7 @@ "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "lodash": "^4.17.5", diff --git a/packages/types/package.json b/packages/types/package.json index c97984e10..6a36b897b 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -30,7 +30,7 @@ "make-promises-safe": "^1.1.0", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@types/node": "^8.0.53", diff --git a/packages/utils/package.json b/packages/utils/package.json index 0fd925715..c596f0620 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -40,7 +40,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/types": "^1.0.1-rc.4", diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index 3f9ee9019..437a1c6b5 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -61,7 +61,7 @@ "shx": "^0.2.2", "tslint": "5.11.0", "typedoc": "0xProject/typedoc", - "typescript": "2.9.2" + "typescript": "3.0.1" }, "dependencies": { "@0xproject/assert": "^1.0.5", diff --git a/packages/website/package.json b/packages/website/package.json index f4638229d..0fcf9c9b9 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -98,7 +98,7 @@ "style-loader": "0.13.x", "tslint": "5.11.0", "tslint-config-0xproject": "^0.0.2", - "typescript": "2.9.2", + "typescript": "3.0.1", "uglifyjs-webpack-plugin": "^1.2.5", "webpack": "^3.1.0", "webpack-dev-middleware": "^1.10.0", -- cgit v1.2.3 From b6cdc00a3145e6b13102676b2a881d0fe52b3a61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 14 Aug 2018 21:51:13 +0000 Subject: Bump copyfiles from 1.2.0 to 2.0.0 Bumps [copyfiles](https://github.com/calvinmetcalf/copyfiles) from 1.2.0 to 2.0.0. - [Release notes](https://github.com/calvinmetcalf/copyfiles/releases) - [Commits](https://github.com/calvinmetcalf/copyfiles/compare/v1.2.0...v2.0.0) Signed-off-by: dependabot[bot] --- packages/0x.js/package.json | 2 +- packages/abi-gen/package.json | 2 +- packages/assert/package.json | 2 +- packages/base-contract/package.json | 2 +- packages/connect/package.json | 2 +- packages/contract-wrappers/package.json | 2 +- packages/contracts/package.json | 2 +- packages/dev-utils/package.json | 2 +- packages/ethereum-types/package.json | 2 +- packages/fill-scenarios/package.json | 2 +- packages/json-schemas/package.json | 2 +- packages/migrations/package.json | 2 +- packages/order-utils/package.json | 2 +- packages/order-watcher/package.json | 2 +- packages/react-docs-example/package.json | 2 +- packages/react-docs/package.json | 2 +- packages/react-shared/package.json | 2 +- packages/sol-compiler/package.json | 2 +- packages/sol-cov/package.json | 2 +- packages/sol-resolver/package.json | 2 +- packages/sra-report/package.json | 2 +- packages/subproviders/package.json | 2 +- packages/tslint-config/package.json | 2 +- packages/types/package.json | 2 +- packages/typescript-typings/package.json | 2 +- packages/utils/package.json | 2 +- packages/web3-wrapper/package.json | 2 +- packages/website/package.json | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) (limited to 'packages') 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 3894be6ea..8f2e423b5 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -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/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/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-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/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/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", -- cgit v1.2.3 From 622509c508272790e3e69c09cf1a1f9696815147 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Mon, 13 Aug 2018 12:23:29 +1000 Subject: [Order-utils] Order is valid when maker amount is very small Previously our min fillable calculation would throw a rounding error when encountering a valid order (with a small maker amount). This was inconsistent with the on-chain logic which allowed this order to be filled. --- packages/contracts/test/exchange/fill_order.ts | 11 ++ .../test/utils/fill_order_combinatorial_utils.ts | 7 ++ .../test/utils/order_factory_from_scenario.ts | 23 ++++ packages/contracts/test/utils/types.ts | 3 +- packages/order-utils/CHANGELOG.json | 4 + packages/order-utils/src/order_state_utils.ts | 36 +++--- .../order-utils/test/order_state_utils_test.ts | 122 +++++++++++++++++++++ packages/order-watcher/test/order_watcher_test.ts | 20 ++-- 8 files changed, 195 insertions(+), 31 deletions(-) create mode 100644 packages/order-utils/test/order_state_utils_test.ts (limited to 'packages') 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/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 6b49d2ee6..86f0da65a 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -2,6 +2,10 @@ { "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 diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index 189bf4180..7974d5d0b 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,10 +23,9 @@ interface SidedOrderRelevantState { traderFeeProxyAllowance: BigNumber; filledTakerAssetAmount: BigNumber; remainingFillableAssetAmount: BigNumber; + isOrderCancelled: boolean; } -const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001; - export class OrderStateUtils { private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; @@ -34,6 +34,9 @@ export class OrderStateUtils { sidedOrderRelevantState: SidedOrderRelevantState, ): void { const isMakerSide = sidedOrderRelevantState.isMakerSide; + if (sidedOrderRelevantState.isOrderCancelled) { + throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled); + } const availableTakerAssetAmount = signedOrder.takerAssetAmount.minus( sidedOrderRelevantState.filledTakerAssetAmount, ); @@ -71,23 +74,15 @@ export class OrderStateUtils { ); } } - - 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, - ) - ) { + const remainingTakerAssetAmount = signedOrder.takerAssetAmount.minus( + sidedOrderRelevantState.filledTakerAssetAmount, + ); + const isRoundingError = OrderValidationUtils.isRoundingError( + remainingTakerAssetAmount, + signedOrder.takerAssetAmount, + signedOrder.makerAssetAmount, + ); + if (isRoundingError) { throw new Error(ExchangeContractErrs.OrderFillRoundingError); } } @@ -101,6 +96,7 @@ export class OrderStateUtils { public async getOpenOrderStateAsync(signedOrder: SignedOrder): Promise { 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,6 +105,7 @@ export class OrderStateUtils { traderFeeProxyAllowance: orderRelevantState.makerFeeProxyAllowance, filledTakerAssetAmount: orderRelevantState.filledTakerAssetAmount, remainingFillableAssetAmount: orderRelevantState.remainingFillableMakerAssetAmount, + isOrderCancelled, }; try { OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState); @@ -278,6 +275,7 @@ export class OrderStateUtils { traderFeeProxyAllowance, filledTakerAssetAmount, remainingFillableAssetAmount, + isOrderCancelled, }; return sidedOrderRelevantState; } 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..9292c40a4 --- /dev/null +++ b/packages/order-utils/test/order_state_utils_test.ts @@ -0,0 +1,122 @@ +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import 'mocha'; + +import { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher, OrderStateUtils } from '../src'; + +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 { + return takerBalance; + }, + async getProxyAllowanceAsync(_assetData: string, _userAddress: string): Promise { + return takerBalance; + }, + }; + return balanceFetcher; + }; + const buildMockOrderFilledFetcher = ( + filledAmount: BigNumber = new BigNumber(0), + cancelled: boolean = false, + ): AbstractOrderFilledCancelledFetcher => { + const orderFetcher = { + async getFilledTakerAmountAsync(_orderHash: string): Promise { + return filledAmount; + }, + async isOrderCancelledAsync(_orderHash: string): Promise { + 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-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index 00962bed0..0f4caeb63 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.OrderAlreadyCancelledOrFilled); }); 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', () => { -- cgit v1.2.3 From 88c99396a2d1b880bffb21ef19507d02b474ba9b Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Wed, 15 Aug 2018 13:03:31 +1000 Subject: Rename OrderAlreadyCancelledOrFilled -> OrderCancelled. Remove try catch of throwing errors in favour of returning the Errors in a OrderValidationResult --- packages/order-utils/src/order_state_utils.ts | 61 ++++++++++++---------- .../order-utils/test/order_state_utils_test.ts | 4 +- packages/order-watcher/test/order_watcher_test.ts | 2 +- packages/types/src/index.ts | 3 +- packages/website/ts/utils/utils.ts | 7 +-- 5 files changed, 40 insertions(+), 37 deletions(-) (limited to 'packages') diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index 7974d5d0b..18fc18bf6 100644 --- a/packages/order-utils/src/order_state_utils.ts +++ b/packages/order-utils/src/order_state_utils.ts @@ -25,6 +25,14 @@ interface SidedOrderRelevantState { remainingFillableAssetAmount: BigNumber; isOrderCancelled: boolean; } +interface OrderValidResult { + isValid: true; +} +interface OrderInvalidResult { + isValid: false; + error: ExchangeContractErrs; +} +type OrderValidationResult = OrderValidResult | OrderInvalidResult; export class OrderStateUtils { private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; @@ -32,46 +40,42 @@ export class OrderStateUtils { private static _validateIfOrderIsValid( signedOrder: SignedOrder, sidedOrderRelevantState: SidedOrderRelevantState, - ): void { + ): OrderValidationResult { const isMakerSide = sidedOrderRelevantState.isMakerSide; if (sidedOrderRelevantState.isOrderCancelled) { - throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled); + 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 }; } } const remainingTakerAssetAmount = signedOrder.takerAssetAmount.minus( @@ -83,8 +87,9 @@ export class OrderStateUtils { signedOrder.makerAssetAmount, ); if (isRoundingError) { - throw new Error(ExchangeContractErrs.OrderFillRoundingError); + return { isValid: false, error: ExchangeContractErrs.OrderFillRoundingError }; } + return { isValid: true }; } constructor( balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher, @@ -107,19 +112,19 @@ export class OrderStateUtils { 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; } diff --git a/packages/order-utils/test/order_state_utils_test.ts b/packages/order-utils/test/order_state_utils_test.ts index 9292c40a4..91ef23b69 100644 --- a/packages/order-utils/test/order_state_utils_test.ts +++ b/packages/order-utils/test/order_state_utils_test.ts @@ -2,7 +2,9 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import 'mocha'; -import { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher, OrderStateUtils } from '../src'; +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'; diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index 0f4caeb63..38bfde7ef 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -501,7 +501,7 @@ 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.OrderAlreadyCancelledOrFilled); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderCancelled); }); orderWatcher.subscribe(callback); await contractWrappers.exchange.cancelOrderAsync(signedOrder); 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/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]: -- cgit v1.2.3