From 7c864b81e0d958560e098ebd8bd241385e4aadff Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 1 Aug 2018 15:08:17 -0700 Subject: Add createOrder with no signing to orderFactory --- packages/order-utils/CHANGELOG.json | 8 ++++++ packages/order-utils/src/constants.ts | 1 + packages/order-utils/src/order_factory.ts | 42 ++++++++++++++++++++++++++----- 3 files changed, 45 insertions(+), 6 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index a399f5ea1..7d9ca0a53 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -1,4 +1,12 @@ [ + { + "version": "1.1.0-rc.2", + "changes": [ + { + "note": "Added a synchronous `createOrder` method in `orderFactory`" + } + ] + }, { "version": "1.0.1-rc.2", "changes": [ diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index bb7482184..92eb89d70 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -10,4 +10,5 @@ export const constants = { ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH: 53, SELECTOR_LENGTH: 4, BASE_16: 16, + INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite }; diff --git a/packages/order-utils/src/order_factory.ts b/packages/order-utils/src/order_factory.ts index 803cb82b1..4be7a1913 100644 --- a/packages/order-utils/src/order_factory.ts +++ b/packages/order-utils/src/order_factory.ts @@ -1,17 +1,17 @@ -import { ECSignature, SignedOrder } from '@0xproject/types'; +import { ECSignature, Order, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Provider } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; +import { constants } from './constants'; import { orderHashUtils } from './order_hash'; import { generatePseudoRandomSalt } from './salt'; import { ecSignOrderHashAsync } from './signature_utils'; import { MessagePrefixType } from './types'; export const orderFactory = { - async createSignedOrderAsync( - provider: Provider, + createOrder( makerAddress: string, takerAddress: string, senderAddress: string, @@ -24,10 +24,9 @@ export const orderFactory = { exchangeAddress: string, feeRecipientAddress: string, expirationTimeSecondsIfExists?: BigNumber, - ): Promise { - const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite + ): Order { const expirationTimeSeconds = _.isUndefined(expirationTimeSecondsIfExists) - ? defaultExpirationUnixTimestampSec + ? constants.INFINITE_TIMESTAMP_SEC : expirationTimeSecondsIfExists; const order = { makerAddress, @@ -44,6 +43,37 @@ export const orderFactory = { feeRecipientAddress, expirationTimeSeconds, }; + return order; + }, + async createSignedOrderAsync( + provider: Provider, + makerAddress: string, + takerAddress: string, + senderAddress: string, + makerFee: BigNumber, + takerFee: BigNumber, + makerAssetAmount: BigNumber, + makerAssetData: string, + takerAssetAmount: BigNumber, + takerAssetData: string, + exchangeAddress: string, + feeRecipientAddress: string, + expirationTimeSecondsIfExists?: BigNumber, + ): Promise { + const order = orderFactory.createOrder( + makerAddress, + takerAddress, + senderAddress, + makerFee, + takerFee, + makerAssetAmount, + makerAssetData, + takerAssetAmount, + takerAssetData, + exchangeAddress, + feeRecipientAddress, + expirationTimeSecondsIfExists, + ); const orderHash = orderHashUtils.getOrderHashHex(order); const messagePrefixOpts = { prefixType: MessagePrefixType.EthSign, -- cgit v1.2.3 From c3e6be7956adf4fabcc8dfffe081515562a1dde0 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 2 Aug 2018 15:53:02 -0700 Subject: Add missing PR numbers --- packages/order-utils/CHANGELOG.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 7d9ca0a53..ddfa690fe 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -3,7 +3,8 @@ "version": "1.1.0-rc.2", "changes": [ { - "note": "Added a synchronous `createOrder` method in `orderFactory`" + "note": "Added a synchronous `createOrder` method in `orderFactory`", + "pr": 935 } ] }, -- cgit v1.2.3 From 4f381ca1d9b6f8ecc232d0481d86f8ba695f7601 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Fri, 3 Aug 2018 15:47:19 -0400 Subject: Update orderFactory interface --- packages/order-utils/src/constants.ts | 1 + packages/order-utils/src/order_factory.ts | 42 +++++++++++++++---------------- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index 92eb89d70..ea3f8b932 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -11,4 +11,5 @@ export const constants = { SELECTOR_LENGTH: 4, BASE_16: 16, INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite + ZERO_AMOUNT: new BigNumber(0), }; diff --git a/packages/order-utils/src/order_factory.ts b/packages/order-utils/src/order_factory.ts index 4be7a1913..444e5a0b2 100644 --- a/packages/order-utils/src/order_factory.ts +++ b/packages/order-utils/src/order_factory.ts @@ -13,21 +13,19 @@ import { MessagePrefixType } from './types'; export const orderFactory = { createOrder( makerAddress: string, - takerAddress: string, - senderAddress: string, - makerFee: BigNumber, - takerFee: BigNumber, makerAssetAmount: BigNumber, makerAssetData: string, takerAssetAmount: BigNumber, takerAssetData: string, exchangeAddress: string, - feeRecipientAddress: string, - expirationTimeSecondsIfExists?: BigNumber, + takerAddress: string = constants.NULL_ADDRESS, + senderAddress: string = constants.NULL_ADDRESS, + makerFee: BigNumber = constants.ZERO_AMOUNT, + takerFee: BigNumber = constants.ZERO_AMOUNT, + feeRecipientAddress: string = constants.NULL_ADDRESS, + salt: BigNumber = generatePseudoRandomSalt(), + expirationTimeSeconds: BigNumber = constants.INFINITE_TIMESTAMP_SEC, ): Order { - const expirationTimeSeconds = _.isUndefined(expirationTimeSecondsIfExists) - ? constants.INFINITE_TIMESTAMP_SEC - : expirationTimeSecondsIfExists; const order = { makerAddress, takerAddress, @@ -38,7 +36,7 @@ export const orderFactory = { takerAssetAmount, makerAssetData, takerAssetData, - salt: generatePseudoRandomSalt(), + salt, exchangeAddress, feeRecipientAddress, expirationTimeSeconds, @@ -48,31 +46,33 @@ export const orderFactory = { async createSignedOrderAsync( provider: Provider, makerAddress: string, - takerAddress: string, - senderAddress: string, - makerFee: BigNumber, - takerFee: BigNumber, makerAssetAmount: BigNumber, makerAssetData: string, takerAssetAmount: BigNumber, takerAssetData: string, exchangeAddress: string, - feeRecipientAddress: string, - expirationTimeSecondsIfExists?: BigNumber, + takerAddress?: string, + senderAddress?: string, + makerFee?: BigNumber, + takerFee?: BigNumber, + feeRecipientAddress?: string, + salt?: BigNumber, + expirationTimeSeconds?: BigNumber, ): Promise { const order = orderFactory.createOrder( makerAddress, - takerAddress, - senderAddress, - makerFee, - takerFee, makerAssetAmount, makerAssetData, takerAssetAmount, takerAssetData, exchangeAddress, + takerAddress, + senderAddress, + makerFee, + takerFee, feeRecipientAddress, - expirationTimeSecondsIfExists, + salt, + expirationTimeSeconds, ); const orderHash = orderHashUtils.getOrderHashHex(order); const messagePrefixOpts = { -- cgit v1.2.3 From d00ee5df0d861e15e258e6747bec4af3284205b2 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Fri, 3 Aug 2018 15:58:17 -0400 Subject: Fix CHANGELOGs --- packages/order-utils/CHANGELOG.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index ddfa690fe..cac29bf6b 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -1,10 +1,10 @@ [ { - "version": "1.1.0-rc.2", + "version": "1.0.1-rc.3", "changes": [ { "note": "Added a synchronous `createOrder` method in `orderFactory`", - "pr": 935 + "pr": 936 } ] }, -- cgit v1.2.3 From 47673ba4bb2932051cb810bd0012c208665eb277 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 5 Aug 2018 16:51:53 -0400 Subject: Update createFactory to accept one createOrderOpts param to encompass all optional params --- packages/order-utils/CHANGELOG.json | 3 +- packages/order-utils/src/order_factory.ts | 70 ++++++++++++++++++------------- 2 files changed, 44 insertions(+), 29 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index cac29bf6b..70a75854a 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -3,7 +3,8 @@ "version": "1.0.1-rc.3", "changes": [ { - "note": "Added a synchronous `createOrder` method in `orderFactory`", + "note": + "Added a synchronous `createOrder` method in `orderFactory`, updated public interfaces to support some optional parameters", "pr": 936 } ] diff --git a/packages/order-utils/src/order_factory.ts b/packages/order-utils/src/order_factory.ts index 444e5a0b2..5901d38c3 100644 --- a/packages/order-utils/src/order_factory.ts +++ b/packages/order-utils/src/order_factory.ts @@ -10,6 +10,16 @@ import { generatePseudoRandomSalt } from './salt'; import { ecSignOrderHashAsync } from './signature_utils'; import { MessagePrefixType } from './types'; +export interface CreateOrderOpts { + takerAddress?: string; + senderAddress?: string; + makerFee?: BigNumber; + takerFee?: BigNumber; + feeRecipientAddress?: string; + salt?: BigNumber; + expirationTimeSeconds?: BigNumber; +} + export const orderFactory = { createOrder( makerAddress: string, @@ -18,28 +28,24 @@ export const orderFactory = { takerAssetAmount: BigNumber, takerAssetData: string, exchangeAddress: string, - takerAddress: string = constants.NULL_ADDRESS, - senderAddress: string = constants.NULL_ADDRESS, - makerFee: BigNumber = constants.ZERO_AMOUNT, - takerFee: BigNumber = constants.ZERO_AMOUNT, - feeRecipientAddress: string = constants.NULL_ADDRESS, - salt: BigNumber = generatePseudoRandomSalt(), - expirationTimeSeconds: BigNumber = constants.INFINITE_TIMESTAMP_SEC, + createOrderOpts: CreateOrderOpts = generateDefaultCreateOrderOpts(), ): Order { + const defaultCreateOrderOpts = generateDefaultCreateOrderOpts(); const order = { makerAddress, - takerAddress, - senderAddress, - makerFee, - takerFee, makerAssetAmount, takerAssetAmount, makerAssetData, takerAssetData, - salt, exchangeAddress, - feeRecipientAddress, - expirationTimeSeconds, + takerAddress: createOrderOpts.takerAddress || defaultCreateOrderOpts.takerAddress, + senderAddress: createOrderOpts.senderAddress || defaultCreateOrderOpts.senderAddress, + makerFee: createOrderOpts.makerFee || defaultCreateOrderOpts.makerFee, + takerFee: createOrderOpts.takerFee || defaultCreateOrderOpts.takerFee, + feeRecipientAddress: createOrderOpts.feeRecipientAddress || defaultCreateOrderOpts.feeRecipientAddress, + salt: createOrderOpts.salt || defaultCreateOrderOpts.salt, + expirationTimeSeconds: + createOrderOpts.expirationTimeSeconds || defaultCreateOrderOpts.expirationTimeSeconds, }; return order; }, @@ -51,13 +57,7 @@ export const orderFactory = { takerAssetAmount: BigNumber, takerAssetData: string, exchangeAddress: string, - takerAddress?: string, - senderAddress?: string, - makerFee?: BigNumber, - takerFee?: BigNumber, - feeRecipientAddress?: string, - salt?: BigNumber, - expirationTimeSeconds?: BigNumber, + createOrderOpts?: CreateOrderOpts, ): Promise { const order = orderFactory.createOrder( makerAddress, @@ -66,13 +66,7 @@ export const orderFactory = { takerAssetAmount, takerAssetData, exchangeAddress, - takerAddress, - senderAddress, - makerFee, - takerFee, - feeRecipientAddress, - salt, - expirationTimeSeconds, + createOrderOpts, ); const orderHash = orderHashUtils.getOrderHashHex(order); const messagePrefixOpts = { @@ -86,6 +80,26 @@ export const orderFactory = { }, }; +function generateDefaultCreateOrderOpts(): { + takerAddress: string; + senderAddress: string; + makerFee: BigNumber; + takerFee: BigNumber; + feeRecipientAddress: string; + salt: BigNumber; + expirationTimeSeconds: BigNumber; +} { + return { + takerAddress: constants.NULL_ADDRESS, + senderAddress: constants.NULL_ADDRESS, + makerFee: constants.ZERO_AMOUNT, + takerFee: constants.ZERO_AMOUNT, + feeRecipientAddress: constants.NULL_ADDRESS, + salt: generatePseudoRandomSalt(), + expirationTimeSeconds: constants.INFINITE_TIMESTAMP_SEC, + }; +} + function getVRSHexString(ecSignature: ECSignature): string { const ETH_SIGN_SIGNATURE_TYPE = '03'; const vrs = `${intToHex(ecSignature.v)}${ethUtil.stripHexPrefix(ecSignature.r)}${ethUtil.stripHexPrefix( -- cgit v1.2.3 From 3cb955c136bf47b5f40cdbc44bcc4d19ec6d6453 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 5 Aug 2018 17:15:58 -0400 Subject: Move CreateOrderOpts into shared types --- packages/order-utils/src/index.ts | 10 +++++++++- packages/order-utils/src/order_factory.ts | 12 +----------- packages/order-utils/src/types.ts | 12 ++++++++++++ 3 files changed, 22 insertions(+), 12 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index 76be63bb8..129eb0a3d 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -13,7 +13,15 @@ export { orderFactory } from './order_factory'; export { constants } from './constants'; export { crypto } from './crypto'; export { generatePseudoRandomSalt } from './salt'; -export { OrderError, MessagePrefixType, MessagePrefixOpts, EIP712Parameter, EIP712Schema, EIP712Types } from './types'; +export { + CreateOrderOpts, + OrderError, + MessagePrefixType, + MessagePrefixOpts, + EIP712Parameter, + EIP712Schema, + EIP712Types, +} from './types'; export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher'; export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher'; export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store'; diff --git a/packages/order-utils/src/order_factory.ts b/packages/order-utils/src/order_factory.ts index 5901d38c3..14727fd97 100644 --- a/packages/order-utils/src/order_factory.ts +++ b/packages/order-utils/src/order_factory.ts @@ -8,17 +8,7 @@ import { constants } from './constants'; import { orderHashUtils } from './order_hash'; import { generatePseudoRandomSalt } from './salt'; import { ecSignOrderHashAsync } from './signature_utils'; -import { MessagePrefixType } from './types'; - -export interface CreateOrderOpts { - takerAddress?: string; - senderAddress?: string; - makerFee?: BigNumber; - takerFee?: BigNumber; - feeRecipientAddress?: string; - salt?: BigNumber; - expirationTimeSeconds?: BigNumber; -} +import { CreateOrderOpts, MessagePrefixType } from './types'; export const orderFactory = { createOrder( diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts index b08e74e71..f44e94349 100644 --- a/packages/order-utils/src/types.ts +++ b/packages/order-utils/src/types.ts @@ -1,3 +1,5 @@ +import { BigNumber } from '@0xproject/utils'; + export enum OrderError { InvalidSignature = 'INVALID_SIGNATURE', } @@ -51,3 +53,13 @@ export enum EIP712Types { String = 'string', Uint256 = 'uint256', } + +export interface CreateOrderOpts { + takerAddress?: string; + senderAddress?: string; + makerFee?: BigNumber; + takerFee?: BigNumber; + feeRecipientAddress?: string; + salt?: BigNumber; + expirationTimeSeconds?: BigNumber; +} -- cgit v1.2.3 From d9933237a0be069d84944e4d4f1b3dffe6bb7643 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 2 Aug 2018 11:21:05 -0700 Subject: Move helper functions into order-utils --- packages/order-utils/src/constants.ts | 2 +- packages/order-utils/src/market_utils.ts | 109 +++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 packages/order-utils/src/market_utils.ts (limited to 'packages/order-utils') diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index ea3f8b932..b18546a6c 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -10,6 +10,6 @@ export const constants = { ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH: 53, SELECTOR_LENGTH: 4, BASE_16: 16, - INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite + INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite, ZERO_AMOUNT: new BigNumber(0), }; diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts new file mode 100644 index 000000000..4ddcc6ec8 --- /dev/null +++ b/packages/order-utils/src/market_utils.ts @@ -0,0 +1,109 @@ +import { schemas } from '@0xproject/json-schemas'; +import { OrderRelevantState, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as _ from 'lodash'; + +import { assert } from './assert'; +import { constants } from './constants'; + +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. + * 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 orderStates An array of objects corresponding to the signedOrders parameter that each contain on-chain state + * relevant to that order. + * @param makerAssetFillAmount The amount of makerAsset desired to be filled. + * @param slippageBufferAmount An additional amount makerAsset to be covered by the result in case of trade collisions or partial fills. + * @return Resulting orders and remaining fill amount that could not be covered by the input. + */ + findOrdersThatCoverMakerAssetFillAmount( + signedOrders: SignedOrder[], + orderStates: OrderRelevantState[], + makerAssetFillAmount: BigNumber, + slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, + ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { + // type assertions + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); + assert.isBigNumber('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 + const result = _.reduce( + signedOrders, + ({ resultOrders, remainingFillAmount }, order, index) => { + if (remainingFillAmount.lessThanOrEqualTo(constants.ZERO_AMOUNT)) { + return { resultOrders, remainingFillAmount: constants.ZERO_AMOUNT }; + } else { + const orderState = orderStates[index]; + const makerAssetAmountAvailable = getMakerAssetAmountAvailable(orderState); + return { + resultOrders: _.concat(resultOrders, order), + remainingFillAmount: remainingFillAmount.minus(makerAssetAmountAvailable), + }; + } + }, + { resultOrders: [] as SignedOrder[], remainingFillAmount: totalFillAmount }, + ); + return result; + }, + /** + * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX (taking into account + * on-chain balances, allowances, and partial fills) in order to fill the takerFees required by signedOrders plus a + * slippageBufferAmount. Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of + * 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 orderStates An array of objects corresponding to the signedOrders parameter that each contain on-chain state + * relevant to 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 feeOrderStates An array of objects corresponding to the signedOrders parameter that each contain on-chain state + * relevant to that order. + * @param makerAssetFillAmount The amount of makerAsset desired to be filled. + * @param slippageBufferAmount An additional amount makerAsset to be covered by the result in case of trade collisions or partial fills. + * @return Resulting orders and remaining fill amount that could not be covered by the input. + */ + findFeeOrdersThatCoverFeesForTargetOrders( + signedOrders: SignedOrder[], + orderStates: OrderRelevantState[], + signedFeeOrders: SignedOrder[], + feeOrderStates: OrderRelevantState[], + slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, + ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { + // type assertions + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + assert.isBigNumber('slippageBufferAmount', slippageBufferAmount); + // calculate total amount of ZRX needed to fill signedOrders + const totalFeeAmount = _.reduce( + signedOrders, + (accFees, order, index) => { + const orderState = orderStates[index]; + const makerAssetAmountAvailable = getMakerAssetAmountAvailable(orderState); + const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable + .div(order.makerAssetAmount) + .mul(order.takerFee); + return accFees.plus(feeToFillMakerAssetAmountAvailable); + }, + constants.ZERO_AMOUNT, + ); + return marketUtils.findOrdersThatCoverMakerAssetFillAmount( + signedFeeOrders, + feeOrderStates, + totalFeeAmount, + slippageBufferAmount, + ); + }, +}; + +const getMakerAssetAmountAvailable = (orderState: OrderRelevantState) => { + return BigNumber.min( + orderState.makerBalance, + orderState.remainingFillableMakerAssetAmount, + orderState.makerProxyAllowance, + ); +}; -- cgit v1.2.3 From 09c0fc94fc91134acfdee1017d7a50e2047b019b Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 2 Aug 2018 13:22:04 -0700 Subject: Implement first round of tests for findOrdersThatCoverMakerAssetFillAmount --- packages/order-utils/src/constants.ts | 1 + packages/order-utils/src/index.ts | 1 + packages/order-utils/src/market_utils.ts | 23 ++-- packages/order-utils/test/market_utils_test.ts | 146 +++++++++++++++++++++ .../order-utils/test/utils/test_order_factory.ts | 63 +++++++++ 5 files changed, 222 insertions(+), 12 deletions(-) create mode 100644 packages/order-utils/test/market_utils_test.ts create mode 100644 packages/order-utils/test/utils/test_order_factory.ts (limited to 'packages/order-utils') diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index b18546a6c..5137ff499 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -2,6 +2,7 @@ import { BigNumber } from '@0xproject/utils'; export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', + NULL_BYTES: '0x', // tslint:disable-next-line:custom-no-magic-numbers UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), TESTRPC_NETWORK_ID: 50, diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index 129eb0a3d..858f500c6 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -32,3 +32,4 @@ export { assetDataUtils } from './asset_data_utils'; export { EIP712Utils } from './eip712_utils'; export { OrderValidationUtils } from './order_validation_utils'; export { ExchangeTransferSimulator } from './exchange_transfer_simulator'; +export { marketUtils } from './market_utils'; diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts index 4ddcc6ec8..710eddf8a 100644 --- a/packages/order-utils/src/market_utils.ts +++ b/packages/order-utils/src/market_utils.ts @@ -39,10 +39,17 @@ export const marketUtils = { return { resultOrders, remainingFillAmount: constants.ZERO_AMOUNT }; } else { const orderState = orderStates[index]; - const makerAssetAmountAvailable = getMakerAssetAmountAvailable(orderState); + const makerAssetAmountAvailable = orderState.remainingFillableMakerAssetAmount; + // if there is no makerAssetAmountAvailable do not append order to resultOrders + // if we have exceeded the total amount we want to fill set remainingFillAmount to 0 return { - resultOrders: _.concat(resultOrders, order), - remainingFillAmount: remainingFillAmount.minus(makerAssetAmountAvailable), + resultOrders: makerAssetAmountAvailable.gt(constants.ZERO_AMOUNT) + ? _.concat(resultOrders, order) + : resultOrders, + remainingFillAmount: BigNumber.max( + constants.ZERO_AMOUNT, + remainingFillAmount.minus(makerAssetAmountAvailable), + ), }; } }, @@ -83,7 +90,7 @@ export const marketUtils = { signedOrders, (accFees, order, index) => { const orderState = orderStates[index]; - const makerAssetAmountAvailable = getMakerAssetAmountAvailable(orderState); + const makerAssetAmountAvailable = orderState.remainingFillableMakerAssetAmount; const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable .div(order.makerAssetAmount) .mul(order.takerFee); @@ -99,11 +106,3 @@ export const marketUtils = { ); }, }; - -const getMakerAssetAmountAvailable = (orderState: OrderRelevantState) => { - return BigNumber.min( - orderState.makerBalance, - orderState.remainingFillableMakerAssetAmount, - orderState.makerProxyAllowance, - ); -}; diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts new file mode 100644 index 000000000..93779d035 --- /dev/null +++ b/packages/order-utils/test/market_utils_test.ts @@ -0,0 +1,146 @@ +import { OrderRelevantState, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import * as _ from 'lodash'; +import 'mocha'; + +import { constants, marketUtils, orderFactory } from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +import { testOrderFactory } from './utils/test_order_factory'; + +chaiSetup.configure(); +const expect = chai.expect; + +// tslint:disable: no-unused-expression +describe('marketUtils', () => { + describe.only('#findOrdersThatCoverMakerAssetFillAmount', () => { + describe('no orders', () => { + it('returns empty and unchanged remainingFillAmount', async () => { + const fillAmount = new BigNumber(10); + const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( + [], + [], + fillAmount, + ); + expect(resultOrders).to.be.empty; + expect(remainingFillAmount).to.be.bignumber.equal(fillAmount); + }); + }); + describe('orders are all completely fillable', () => { + // generate three signed orders each with 10 units of makerAsset, 30 total + const testOrderCount = 3; + const makerAssetAmount = new BigNumber(10); + const inputOrders = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + }, + testOrderCount, + ); + // generate order states that cover the required fill amount + const inputOrderStates = testOrderFactory.generateTestOrderRelevantStates( + { + remainingFillableMakerAssetAmount: makerAssetAmount, + }, + testOrderCount, + ); + it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => { + // try to fill 30 units of makerAsset + const fillAmount = new BigNumber(30); + const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( + inputOrders, + inputOrderStates, + fillAmount, + ); + expect(resultOrders).to.be.deep.equal(inputOrders); + expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); + }); + it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => { + // try to fill 25 units of makerAsset + const fillAmount = new BigNumber(25); + const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( + inputOrders, + inputOrderStates, + fillAmount, + ); + expect(resultOrders).to.be.deep.equal(inputOrders); + expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); + }); + it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => { + // try to fill 35 units of makerAsset + const fillAmount = new BigNumber(35); + const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( + inputOrders, + inputOrderStates, + fillAmount, + ); + expect(resultOrders).to.be.deep.equal(inputOrders); + expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5)); + }); + it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => { + // try to fill 10 units of makerAsset + const fillAmount = new BigNumber(10); + const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( + inputOrders, + inputOrderStates, + fillAmount, + ); + expect(resultOrders).to.be.deep.equal([inputOrders[0]]); + expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); + }); + it('returns first two orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => { + // try to fill 15 units of makerAsset + const fillAmount = new BigNumber(15); + const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( + inputOrders, + inputOrderStates, + fillAmount, + ); + expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]); + expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); + }); + }); + describe('orders are partially fillable', () => { + // generate three signed orders each with 10 units of makerAsset, 30 total + const testOrderCount = 3; + const makerAssetAmount = new BigNumber(10); + const inputOrders = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + }, + testOrderCount, + ); + // generate order states that cover different scenarios + // 1. order is completely filled already + // 2. order is partially fillable + // 3. order is completely fillable + const partialOrderStates: Array> = [ + { + remainingFillableMakerAssetAmount: constants.ZERO_AMOUNT, + }, + { + remainingFillableMakerAssetAmount: new BigNumber(5), + }, + { + remainingFillableMakerAssetAmount: makerAssetAmount, + }, + ]; + const inputOrderStates: OrderRelevantState[] = _.map( + partialOrderStates, + testOrderFactory.generateTestOrderRelevantState, + ); + it('returns last 2 orders and non-zero remainingFillAmount when trying to fill original makerAssetAmounts', async () => { + // try to fill 30 units of makerAsset + const fillAmount = new BigNumber(30); + const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( + inputOrders, + inputOrderStates, + fillAmount, + ); + expect(resultOrders).to.be.deep.equal([inputOrders[1], inputOrders[2]]); + expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(15)); + }); + }); + }); + describe('#findFeeOrdersThatCoverFeesForTargetOrders', () => {}); +}); diff --git a/packages/order-utils/test/utils/test_order_factory.ts b/packages/order-utils/test/utils/test_order_factory.ts new file mode 100644 index 000000000..2c5d8cf61 --- /dev/null +++ b/packages/order-utils/test/utils/test_order_factory.ts @@ -0,0 +1,63 @@ +import { Order, OrderRelevantState, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as _ from 'lodash'; + +import { constants, orderFactory } from '../../src'; + +const BASE_TEST_ORDER: Order = orderFactory.createOrder( + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, + constants.ZERO_AMOUNT, + constants.ZERO_AMOUNT, + constants.ZERO_AMOUNT, + constants.NULL_BYTES, + constants.ZERO_AMOUNT, + constants.NULL_BYTES, + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, +); +const BASE_TEST_SIGNED_ORDER: SignedOrder = { + ...BASE_TEST_ORDER, + signature: constants.NULL_BYTES, +}; +const BASE_TEST_ORDER_RELEVANT_STATE: OrderRelevantState = { + makerBalance: constants.ZERO_AMOUNT, + makerProxyAllowance: constants.ZERO_AMOUNT, + makerFeeBalance: constants.ZERO_AMOUNT, + makerFeeProxyAllowance: constants.ZERO_AMOUNT, + filledTakerAssetAmount: constants.ZERO_AMOUNT, + remainingFillableMakerAssetAmount: constants.ZERO_AMOUNT, + remainingFillableTakerAssetAmount: constants.ZERO_AMOUNT, +}; + +export const testOrderFactory = { + generateTestSignedOrder(partialOrder: Partial): SignedOrder { + return transformObject(BASE_TEST_SIGNED_ORDER, partialOrder); + }, + generateTestSignedOrders(partialOrder: Partial, numOrders: number): SignedOrder[] { + const baseTestOrders = generateArrayOfInput(BASE_TEST_SIGNED_ORDER, numOrders); + return transformObjects(baseTestOrders, partialOrder); + }, + generateTestOrderRelevantState(partialOrderRelevantState: Partial): OrderRelevantState { + return transformObject(BASE_TEST_ORDER_RELEVANT_STATE, partialOrderRelevantState); + }, + generateTestOrderRelevantStates( + partialOrderRelevantState: Partial, + numOrderStates: number, + ): OrderRelevantState[] { + const baseTestOrderStates = generateArrayOfInput(BASE_TEST_ORDER_RELEVANT_STATE, numOrderStates); + return transformObjects(baseTestOrderStates, partialOrderRelevantState); + }, +}; + +function generateArrayOfInput(input: T, rangeLength: number): T[] { + return _.map(_.range(rangeLength), () => input); +} +function transformObject(input: T, transformation: Partial): T { + const copy = _.cloneDeep(input); + return _.assign(copy, transformation); +} +function transformObjects(inputs: T[], transformation: Partial): T[] { + return _.map(inputs, input => transformObject(input, transformation)); +} -- cgit v1.2.3 From bc5f8e52de9dfe920ce1d0e6b44c90a5a5826cbe Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 2 Aug 2018 15:47:29 -0700 Subject: Change orderStates param name to remaingFillableMakerAssetAmounts --- packages/order-utils/src/market_utils.ts | 85 ++++++++++++++-------- packages/order-utils/test/market_utils_test.ts | 43 +++-------- .../order-utils/test/utils/test_order_factory.ts | 32 +------- 3 files changed, 69 insertions(+), 91 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts index 710eddf8a..d66448a0b 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 { OrderRelevantState, SignedOrder } from '@0xproject/types'; +import { SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; @@ -11,24 +11,33 @@ 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. * 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 orderStates An array of objects corresponding to the signedOrders parameter that each contain on-chain state - * relevant to that order. - * @param makerAssetFillAmount The amount of makerAsset desired to be filled. - * @param slippageBufferAmount An additional amount 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 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 makerAsset to be covered by the result in case of trade collisions or partial fills. * @return Resulting orders and remaining fill amount that could not be covered by the input. */ findOrdersThatCoverMakerAssetFillAmount( signedOrders: SignedOrder[], - orderStates: OrderRelevantState[], + remainingFillableMakerAssetAmounts: BigNumber[], makerAssetFillAmount: BigNumber, slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { // type assertions assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); - assert.isBigNumber('slippageBufferAmount', slippageBufferAmount); + _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => + assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), + ); + assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount); + assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount); + // other assertions + assert.assert( + signedOrders.length === remainingFillableMakerAssetAmounts.length, + 'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length', + ); // 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 @@ -38,8 +47,7 @@ export const marketUtils = { if (remainingFillAmount.lessThanOrEqualTo(constants.ZERO_AMOUNT)) { return { resultOrders, remainingFillAmount: constants.ZERO_AMOUNT }; } else { - const orderState = orderStates[index]; - const makerAssetAmountAvailable = orderState.remainingFillableMakerAssetAmount; + const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index]; // if there is no makerAssetAmountAvailable do not append order to resultOrders // if we have exceeded the total amount we want to fill set remainingFillAmount to 0 return { @@ -62,47 +70,64 @@ export const marketUtils = { * 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 * 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 orderStates An array of objects corresponding to the signedOrders parameter that each contain on-chain state - * relevant to 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 feeOrderStates An array of objects corresponding to the signedOrders parameter that each contain on-chain state - * relevant to that order. - * @param makerAssetFillAmount The amount of makerAsset desired to be filled. - * @param slippageBufferAmount An additional amount 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 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 makerAsset to be covered by the result in case of trade collisions or partial fills. * @return Resulting orders and remaining fill amount that could not be covered by the input. */ findFeeOrdersThatCoverFeesForTargetOrders( signedOrders: SignedOrder[], - orderStates: OrderRelevantState[], + remainingFillableMakerAssetAmounts: BigNumber[], signedFeeOrders: SignedOrder[], - feeOrderStates: OrderRelevantState[], + remainingFillableFeeAmounts: BigNumber[], slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { // type assertions assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => + assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), + ); assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); - assert.isBigNumber('slippageBufferAmount', slippageBufferAmount); + _.forEach(remainingFillableFeeAmounts, (amount, index) => + assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), + ); + assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount); + // other assertions + assert.assert( + signedOrders.length === remainingFillableMakerAssetAmounts.length, + 'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length', + ); + assert.assert( + signedOrders.length === remainingFillableMakerAssetAmounts.length, + 'Expected signedFeeOrders.length to equal remainingFillableFeeAmounts.length', + ); // calculate total amount of ZRX needed to fill signedOrders const totalFeeAmount = _.reduce( signedOrders, (accFees, order, index) => { - const orderState = orderStates[index]; - const makerAssetAmountAvailable = orderState.remainingFillableMakerAssetAmount; + const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index]; const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable - .div(order.makerAssetAmount) - .mul(order.takerFee); + .mul(order.takerFee) + .div(order.makerAssetAmount); return accFees.plus(feeToFillMakerAssetAmountAvailable); }, constants.ZERO_AMOUNT, ); return marketUtils.findOrdersThatCoverMakerAssetFillAmount( signedFeeOrders, - feeOrderStates, + remainingFillableFeeAmounts, totalFeeAmount, slippageBufferAmount, ); + // TODO: add more orders here to cover rounding + // https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarding-contract-specification.md#over-buying-zrx }, }; diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts index 93779d035..ac3fb9b93 100644 --- a/packages/order-utils/test/market_utils_test.ts +++ b/packages/order-utils/test/market_utils_test.ts @@ -1,10 +1,8 @@ -import { OrderRelevantState, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; -import * as _ from 'lodash'; import 'mocha'; -import { constants, marketUtils, orderFactory } from '../src'; +import { constants, marketUtils } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { testOrderFactory } from './utils/test_order_factory'; @@ -37,19 +35,14 @@ describe('marketUtils', () => { }, testOrderCount, ); - // generate order states that cover the required fill amount - const inputOrderStates = testOrderFactory.generateTestOrderRelevantStates( - { - remainingFillableMakerAssetAmount: makerAssetAmount, - }, - testOrderCount, - ); + // 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 30 units of makerAsset const fillAmount = new BigNumber(30); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - inputOrderStates, + remainingFillableMakerAssetAmounts, fillAmount, ); expect(resultOrders).to.be.deep.equal(inputOrders); @@ -60,7 +53,7 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(25); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - inputOrderStates, + remainingFillableMakerAssetAmounts, fillAmount, ); expect(resultOrders).to.be.deep.equal(inputOrders); @@ -71,7 +64,7 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(35); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - inputOrderStates, + remainingFillableMakerAssetAmounts, fillAmount, ); expect(resultOrders).to.be.deep.equal(inputOrders); @@ -82,7 +75,7 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - inputOrderStates, + remainingFillableMakerAssetAmounts, fillAmount, ); expect(resultOrders).to.be.deep.equal([inputOrders[0]]); @@ -93,7 +86,7 @@ describe('marketUtils', () => { const fillAmount = new BigNumber(15); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - inputOrderStates, + remainingFillableMakerAssetAmounts, fillAmount, ); expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]); @@ -110,31 +103,17 @@ describe('marketUtils', () => { }, testOrderCount, ); - // generate order states that cover different scenarios + // generate remainingFillableMakerAssetAmounts that cover different partial fill scenarios // 1. order is completely filled already // 2. order is partially fillable // 3. order is completely fillable - const partialOrderStates: Array> = [ - { - remainingFillableMakerAssetAmount: constants.ZERO_AMOUNT, - }, - { - remainingFillableMakerAssetAmount: new BigNumber(5), - }, - { - remainingFillableMakerAssetAmount: makerAssetAmount, - }, - ]; - const inputOrderStates: OrderRelevantState[] = _.map( - partialOrderStates, - testOrderFactory.generateTestOrderRelevantState, - ); + const remainingFillableMakerAssetAmounts = [constants.ZERO_AMOUNT, new BigNumber(5), makerAssetAmount]; it('returns last 2 orders and non-zero remainingFillAmount when trying to fill original makerAssetAmounts', async () => { // try to fill 30 units of makerAsset const fillAmount = new BigNumber(30); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, - inputOrderStates, + remainingFillableMakerAssetAmounts, fillAmount, ); expect(resultOrders).to.be.deep.equal([inputOrders[1], inputOrders[2]]); diff --git a/packages/order-utils/test/utils/test_order_factory.ts b/packages/order-utils/test/utils/test_order_factory.ts index 2c5d8cf61..611e777ea 100644 --- a/packages/order-utils/test/utils/test_order_factory.ts +++ b/packages/order-utils/test/utils/test_order_factory.ts @@ -1,5 +1,4 @@ -import { Order, OrderRelevantState, SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { Order, SignedOrder } from '@0xproject/types'; import * as _ from 'lodash'; import { constants, orderFactory } from '../../src'; @@ -21,43 +20,18 @@ const BASE_TEST_SIGNED_ORDER: SignedOrder = { ...BASE_TEST_ORDER, signature: constants.NULL_BYTES, }; -const BASE_TEST_ORDER_RELEVANT_STATE: OrderRelevantState = { - makerBalance: constants.ZERO_AMOUNT, - makerProxyAllowance: constants.ZERO_AMOUNT, - makerFeeBalance: constants.ZERO_AMOUNT, - makerFeeProxyAllowance: constants.ZERO_AMOUNT, - filledTakerAssetAmount: constants.ZERO_AMOUNT, - remainingFillableMakerAssetAmount: constants.ZERO_AMOUNT, - remainingFillableTakerAssetAmount: constants.ZERO_AMOUNT, -}; export const testOrderFactory = { generateTestSignedOrder(partialOrder: Partial): SignedOrder { return transformObject(BASE_TEST_SIGNED_ORDER, partialOrder); }, generateTestSignedOrders(partialOrder: Partial, numOrders: number): SignedOrder[] { - const baseTestOrders = generateArrayOfInput(BASE_TEST_SIGNED_ORDER, numOrders); - return transformObjects(baseTestOrders, partialOrder); - }, - generateTestOrderRelevantState(partialOrderRelevantState: Partial): OrderRelevantState { - return transformObject(BASE_TEST_ORDER_RELEVANT_STATE, partialOrderRelevantState); - }, - generateTestOrderRelevantStates( - partialOrderRelevantState: Partial, - numOrderStates: number, - ): OrderRelevantState[] { - const baseTestOrderStates = generateArrayOfInput(BASE_TEST_ORDER_RELEVANT_STATE, numOrderStates); - return transformObjects(baseTestOrderStates, partialOrderRelevantState); + const baseTestOrders = _.map(_.range(numOrders), () => BASE_TEST_SIGNED_ORDER); + return _.map(baseTestOrders, order => transformObject(order, partialOrder)); }, }; -function generateArrayOfInput(input: T, rangeLength: number): T[] { - return _.map(_.range(rangeLength), () => input); -} function transformObject(input: T, transformation: Partial): T { const copy = _.cloneDeep(input); return _.assign(copy, transformation); } -function transformObjects(inputs: T[], transformation: Partial): T[] { - return _.map(inputs, input => transformObject(input, transformation)); -} -- cgit v1.2.3 From 8382161f7553539ed6f436be88df8672b00bf35e Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 5 Aug 2018 20:48:56 -0400 Subject: Add tests for findFeeOrdersThatCoverFeesForTargetOrders --- packages/order-utils/src/constants.ts | 2 +- packages/order-utils/src/market_utils.ts | 14 +- packages/order-utils/test/market_utils_test.ts | 162 ++++++++++++++++++++- .../order-utils/test/utils/test_order_factory.ts | 7 +- 4 files changed, 165 insertions(+), 20 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index 5137ff499..c23578c20 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -11,6 +11,6 @@ export const constants = { ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH: 53, SELECTOR_LENGTH: 4, BASE_16: 16, - INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite, + INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite ZERO_AMOUNT: new BigNumber(0), }; diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts index d66448a0b..94b5be4eb 100644 --- a/packages/order-utils/src/market_utils.ts +++ b/packages/order-utils/src/market_utils.ts @@ -17,7 +17,7 @@ export const marketUtils = { * 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 makerAsset to be covered by the result in case of trade collisions or partial fills. + * @param slippageBufferAmount An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills. * @return Resulting orders and remaining fill amount that could not be covered by the input. */ findOrdersThatCoverMakerAssetFillAmount( @@ -80,8 +80,8 @@ export const marketUtils = { * @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 makerAsset to be covered by the result in case of trade collisions or partial fills. - * @return Resulting orders and remaining fill amount that could not be covered by the input. + * @param slippageBufferAmount An additional amount of fee to be covered by the result in case of trade collisions or partial fills. + * @return Resulting orders and remaining fee amount that could not be covered by the input. */ findFeeOrdersThatCoverFeesForTargetOrders( signedOrders: SignedOrder[], @@ -89,7 +89,7 @@ export const marketUtils = { signedFeeOrders: SignedOrder[], remainingFillableFeeAmounts: BigNumber[], slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, - ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { + ): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } { // type assertions assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => @@ -121,12 +121,16 @@ export const marketUtils = { }, constants.ZERO_AMOUNT, ); - return marketUtils.findOrdersThatCoverMakerAssetFillAmount( + const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( signedFeeOrders, remainingFillableFeeAmounts, totalFeeAmount, slippageBufferAmount, ); + return { + resultOrders, + remainingFeeAmount: remainingFillAmount, + }; // TODO: add more orders here to cover rounding // https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarding-contract-specification.md#over-buying-zrx }, diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts index ac3fb9b93..03f86c581 100644 --- a/packages/order-utils/test/market_utils_test.ts +++ b/packages/order-utils/test/market_utils_test.ts @@ -12,7 +12,7 @@ const expect = chai.expect; // tslint:disable: no-unused-expression describe('marketUtils', () => { - describe.only('#findOrdersThatCoverMakerAssetFillAmount', () => { + describe('#findOrdersThatCoverMakerAssetFillAmount', () => { describe('no orders', () => { it('returns empty and unchanged remainingFillAmount', async () => { const fillAmount = new BigNumber(10); @@ -25,15 +25,14 @@ describe('marketUtils', () => { expect(remainingFillAmount).to.be.bignumber.equal(fillAmount); }); }); - describe('orders are all completely fillable', () => { + describe('orders are completely fillable', () => { // generate three signed orders each with 10 units of makerAsset, 30 total - const testOrderCount = 3; const makerAssetAmount = new BigNumber(10); const inputOrders = testOrderFactory.generateTestSignedOrders( { makerAssetAmount, }, - testOrderCount, + 3, ); // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; @@ -95,20 +94,19 @@ describe('marketUtils', () => { }); describe('orders are partially fillable', () => { // generate three signed orders each with 10 units of makerAsset, 30 total - const testOrderCount = 3; const makerAssetAmount = new BigNumber(10); const inputOrders = testOrderFactory.generateTestSignedOrders( { makerAssetAmount, }, - testOrderCount, + 3, ); // generate remainingFillableMakerAssetAmounts that cover different partial fill scenarios // 1. order is completely filled already // 2. order is partially fillable // 3. order is completely fillable const remainingFillableMakerAssetAmounts = [constants.ZERO_AMOUNT, new BigNumber(5), makerAssetAmount]; - it('returns last 2 orders and non-zero remainingFillAmount when trying to fill original makerAssetAmounts', async () => { + it('returns last two orders and non-zero remainingFillAmount when trying to fill original makerAssetAmounts', async () => { // try to fill 30 units of makerAsset const fillAmount = new BigNumber(30); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( @@ -121,5 +119,153 @@ describe('marketUtils', () => { }); }); }); - describe('#findFeeOrdersThatCoverFeesForTargetOrders', () => {}); + describe('#findFeeOrdersThatCoverFeesForTargetOrders', () => { + // generate three signed fee orders each with 10 units of ZRX, 30 total + const zrxAmount = new BigNumber(10); + const inputFeeOrders = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount: zrxAmount, + }, + 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); + }); + }); + describe('no fee orders', () => { + // generate three signed orders each with 10 units of makerAsset, 30 total + // each signed order requires 10 units of takerFee + const makerAssetAmount = new BigNumber(10); + const takerFee = new BigNumber(10); + const inputOrders = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + takerFee, + }, + 3, + ); + // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount + const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; + it('returns empty and non-zero remainingFeeAmount', async () => { + const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( + inputOrders, + remainingFillableMakerAssetAmounts, + [], + [], + ); + expect(resultOrders).to.be.empty; + expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); + }); + }); + describe('target orders have no fees', () => { + // generate three signed orders each with 10 units of makerAsset, 30 total + const makerAssetAmount = new BigNumber(10); + const inputOrders = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + }, + 3, + ); + // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount + const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; + it('returns empty and zero remainingFeeAmount', async () => { + const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( + inputOrders, + remainingFillableMakerAssetAmounts, + inputFeeOrders, + remainingFillableFeeAmounts, + ); + expect(resultOrders).to.be.empty; + expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); + }); + }); + describe('target orders require fees and are completely fillable', () => { + // generate three signed orders each with 10 units of makerAsset, 30 total + // each signed order requires 10 units of takerFee + const makerAssetAmount = new BigNumber(10); + const takerFee = new BigNumber(10); + const inputOrders = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + takerFee, + }, + 3, + ); + // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount + const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; + it('returns input fee orders and zero remainingFeeAmount', async () => { + const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( + inputOrders, + remainingFillableMakerAssetAmounts, + inputFeeOrders, + remainingFillableFeeAmounts, + ); + expect(resultOrders).to.be.deep.equal(inputFeeOrders); + expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); + }); + }); + describe('target orders require fees and are partially fillable', () => { + // generate three signed orders each with 10 units of makerAsset, 30 total + // each signed order requires 10 units of takerFee + const makerAssetAmount = new BigNumber(10); + const takerFee = new BigNumber(10); + const inputOrders = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + takerFee, + }, + 3, + ); + // generate remainingFillableMakerAssetAmounts that cover different partial fill scenarios + // 1. order is completely filled already + // 2. order is partially fillable + // 3. order is completely fillable + const remainingFillableMakerAssetAmounts = [constants.ZERO_AMOUNT, new BigNumber(5), makerAssetAmount]; + it('returns first two input fee orders and zero remainingFeeAmount', async () => { + const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( + inputOrders, + remainingFillableMakerAssetAmounts, + inputFeeOrders, + remainingFillableFeeAmounts, + ); + expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]); + expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); + }); + }); + describe('target orders require more fees than available', () => { + // generate three signed orders each with 10 units of makerAsset, 30 total + // each signed order requires 20 units of takerFee + const makerAssetAmount = new BigNumber(10); + const takerFee = new BigNumber(20); + const inputOrders = testOrderFactory.generateTestSignedOrders( + { + makerAssetAmount, + takerFee, + }, + 3, + ); + // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount + const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; + it('returns input fee orders and non-zero remainingFeeAmount', async () => { + const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( + inputOrders, + remainingFillableMakerAssetAmounts, + inputFeeOrders, + remainingFillableFeeAmounts, + ); + expect(resultOrders).to.be.deep.equal(inputFeeOrders); + expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); + }); + }); + }); }); diff --git a/packages/order-utils/test/utils/test_order_factory.ts b/packages/order-utils/test/utils/test_order_factory.ts index 611e777ea..75dc6f1f2 100644 --- a/packages/order-utils/test/utils/test_order_factory.ts +++ b/packages/order-utils/test/utils/test_order_factory.ts @@ -5,14 +5,9 @@ import { constants, orderFactory } from '../../src'; const BASE_TEST_ORDER: Order = orderFactory.createOrder( constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.ZERO_AMOUNT, constants.ZERO_AMOUNT, + constants.NULL_ADDRESS, constants.ZERO_AMOUNT, - constants.NULL_BYTES, - constants.ZERO_AMOUNT, - constants.NULL_BYTES, constants.NULL_ADDRESS, constants.NULL_ADDRESS, ); -- cgit v1.2.3 From 7d0bec9b2a9960390b0b3b19e5ed4d84a679669b Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 5 Aug 2018 20:54:29 -0400 Subject: Add some test cases that stress slippageBufferAmount param --- packages/order-utils/test/market_utils_test.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts index 03f86c581..21c0a4802 100644 --- a/packages/order-utils/test/market_utils_test.ts +++ b/packages/order-utils/test/market_utils_test.ts @@ -37,34 +37,43 @@ describe('marketUtils', () => { // 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 30 units of makerAsset - const fillAmount = new BigNumber(30); + // try to fill 20 units of makerAsset + // include 10 units of slippageBufferAmount + const fillAmount = new BigNumber(20); + const slippageBufferAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, remainingFillableMakerAssetAmounts, fillAmount, + slippageBufferAmount, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); }); it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => { - // try to fill 25 units of makerAsset - const fillAmount = new BigNumber(25); + // try to fill 15 units of makerAsset + // include 10 units of slippageBufferAmount + const fillAmount = new BigNumber(15); + const slippageBufferAmount = new BigNumber(10); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, remainingFillableMakerAssetAmounts, fillAmount, + slippageBufferAmount, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); }); it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => { - // try to fill 35 units of makerAsset - const fillAmount = new BigNumber(35); + // try to fill 30 units of makerAsset + // include 5 units of slippageBufferAmount + const fillAmount = new BigNumber(30); + const slippageBufferAmount = new BigNumber(5); const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( inputOrders, remainingFillableMakerAssetAmounts, fillAmount, + slippageBufferAmount, ); expect(resultOrders).to.be.deep.equal(inputOrders); expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5)); -- cgit v1.2.3 From 2273798df9c5b625a678fefaa2f49e7e1cb99d0f Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 5 Aug 2018 20:58:57 -0400 Subject: Update CHANGELOGs --- packages/order-utils/CHANGELOG.json | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages/order-utils') diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 70a75854a..776bd67ec 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -6,6 +6,10 @@ "note": "Added a synchronous `createOrder` method in `orderFactory`, updated public interfaces to support some optional parameters", "pr": 936 + }, + { + "note": "Added marketUtils", + "pr": 937 } ] }, -- cgit v1.2.3 From 35201af4b1aa64a0961de0d13ce9c5bac65ddbf8 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 6 Aug 2018 16:35:49 -0400 Subject: Remove assertion comments --- packages/order-utils/src/market_utils.ts | 4 ---- 1 file changed, 4 deletions(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts index 94b5be4eb..681059ddf 100644 --- a/packages/order-utils/src/market_utils.ts +++ b/packages/order-utils/src/market_utils.ts @@ -26,14 +26,12 @@ export const marketUtils = { makerAssetFillAmount: BigNumber, slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, ): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } { - // type assertions assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), ); assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount); assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount); - // other assertions assert.assert( signedOrders.length === remainingFillableMakerAssetAmounts.length, 'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length', @@ -90,7 +88,6 @@ export const marketUtils = { remainingFillableFeeAmounts: BigNumber[], slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT, ): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } { - // type assertions assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), @@ -100,7 +97,6 @@ export const marketUtils = { assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), ); assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount); - // other assertions assert.assert( signedOrders.length === remainingFillableMakerAssetAmounts.length, 'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length', -- cgit v1.2.3 From 6e2e658162a5a128b722ba105f92fa5267c4bd62 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Wed, 8 Aug 2018 11:27:38 -0700 Subject: Update TypeScript to version 2.9.2 --- packages/order-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index cab917a82..7880b9352 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.7.1" + "typescript": "2.9.2" }, "dependencies": { "@0xproject/assert": "^1.0.4", -- cgit v1.2.3 From 6a5965d73bb542634631d7af76c150795d899744 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Thu, 26 Jul 2018 14:11:03 -0700 Subject: Add strictArgumentEncodingCheck to BaseContract and use it in contract templates --- packages/order-utils/test/signature_utils_test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'packages/order-utils') diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts index 5714f9671..baae2b414 100644 --- a/packages/order-utils/test/signature_utils_test.ts +++ b/packages/order-utils/test/signature_utils_test.ts @@ -22,7 +22,8 @@ describe('Signature utils', () => { let address = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; it("should return false if the data doesn't pertain to the signature & address", async () => { - expect(await isValidSignatureAsync(provider, '0x0', ethSignSignature, address)).to.be.false(); + const bytes32Zeros = '0x0000000000000000000000000000000000000000000000000000000000000000'; + expect(await isValidSignatureAsync(provider, bytes32Zeros, ethSignSignature, address)).to.be.false(); }); it("should return false if the address doesn't pertain to the signature & data", async () => { const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42'; -- cgit v1.2.3 From 762bbe9bcd79ca5b832859cc20ffa4c83603cbcb Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Wed, 8 Aug 2018 16:44:52 -0700 Subject: Update remaining CHANGELOG.json files --- packages/order-utils/CHANGELOG.json | 3 +++ 1 file changed, 3 insertions(+) (limited to 'packages/order-utils') diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 776bd67ec..fa82976ad 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -10,6 +10,9 @@ { "note": "Added marketUtils", "pr": 937 + }, + { + "note": "Dependencies updated" } ] }, -- cgit v1.2.3