diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json
index f3f843e37e..0fabf63a12 100644
--- a/packages/asset-swapper/CHANGELOG.json
+++ b/packages/asset-swapper/CHANGELOG.json
@@ -1,4 +1,17 @@
[
+ {
+ "version": "2.1.0-beta.3",
+ "changes": [
+ {
+ "note": "Refactor of logic for marketBuy/marketSell order pruning and selecting, introduced protocol fees, and refactored types used by the package",
+ "pr": 2272
+ },
+ {
+ "note": "Incorporate paying protocol fees.",
+ "pr": 2350
+ }
+ ]
+ },
{
"version": "2.1.0-beta.2",
"changes": [
@@ -7,7 +20,7 @@
"pr": 2342
}
],
- "timestamp": 1574030254
+ "timestamp": 1573159180
},
{
"version": "2.1.0-beta.1",
diff --git a/packages/asset-swapper/CHANGELOG.md b/packages/asset-swapper/CHANGELOG.md
index b83b2535ef..a9c2f3a6cf 100644
--- a/packages/asset-swapper/CHANGELOG.md
+++ b/packages/asset-swapper/CHANGELOG.md
@@ -5,10 +5,6 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
-## v2.1.0-beta.2 - _November 17, 2019_
-
- * Update BigNumber version to ~9.0.0 (#2342)
-
## v2.1.0-beta.1 - _November 7, 2019_
* All references to network ID have been removed, and references to chain ID have been introduced instead (#2313)
diff --git a/packages/asset-swapper/docs/reference.mdx b/packages/asset-swapper/docs/reference.mdx
index 69482509a5..96af714365 100644
--- a/packages/asset-swapper/docs/reference.mdx
+++ b/packages/asset-swapper/docs/reference.mdx
@@ -1,45 +1,42 @@
-# Interface: TupleDataItem
+# Interface: Web3JsV1Provider
+
+Web3.js version 1 provider interface
+This provider interface was implemented in the pre-1.0Beta releases for Web3.js.
+This interface allowed sending synchonous requests, support for which was later dropped.
-## Properties
+## Methods
-### components
+### send
-• **components**: *[DataItem](#class-dataitem)[]*
+▸ **send**(`payload`: [JSONRPCRequestPayload](_ethereum_types_src_index_.jsonrpcrequestpayload.md)): *[JSONRPCResponsePayload](#class-jsonrpcresponsepayload)*
-*Overrides [DataItem](_ethereum_types_src_index_.dataitem.md).[components](#optional-components)*
+*Defined in [ethereum-types/src/index.ts:45](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L45)*
-*Defined in [ethereum-types/src/index.ts:142](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L142)*
+**Parameters:**
+
+Name | Type |
+------ | ------ |
+`payload` | [JSONRPCRequestPayload](#class-jsonrpcrequestpayload) |
+
+**Returns:** *[JSONRPCResponsePayload](#class-jsonrpcresponsepayload)*
___
-### `Optional` internalType
+### sendAsync
-• **internalType**? : *undefined | string*
+▸ **sendAsync**(`payload`: [JSONRPCRequestPayload](_ethereum_types_src_index_.jsonrpcrequestpayload.md), `callback`: [JSONRPCErrorCallback](#jsonrpcerrorcallback)): *void*
-*Inherited from [DataItem](#interface-dataitem).[internalType](#optional-internaltype)*
+*Defined in [ethereum-types/src/index.ts:44](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L44)*
-*Defined in [ethereum-types/src/index.ts:137](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L137)*
+**Parameters:**
-___
+Name | Type |
+------ | ------ |
+`payload` | [JSONRPCRequestPayload](#class-jsonrpcrequestpayload) |
+`callback` | [JSONRPCErrorCallback](#jsonrpcerrorcallback) |
-### name
-
-• **name**: *string*
-
-*Inherited from [DataItem](#interface-dataitem).[name](#name)*
-
-*Defined in [ethereum-types/src/index.ts:135](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L135)*
-
-___
-
-### type
-
-• **type**: *string*
-
-*Inherited from [DataItem](#interface-dataitem).[type](#type)*
-
-*Defined in [ethereum-types/src/index.ts:136](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L136)*
+**Returns:** *void*
@@ -57,7 +54,7 @@ ___
\+ **new SwapQuoteConsumer**(`supportedProvider`: [SupportedProvider](#supportedprovider), `options`: `Partial`): *[SwapQuoteConsumer](#class-swapquoteconsumer)*
-*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:31](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L31)*
+*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:39](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L39)*
**Parameters:**
@@ -74,7 +71,7 @@ Name | Type | Default |
• **chainId**: *number*
-*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:27](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L27)*
+*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:28](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L28)*
___
@@ -82,26 +79,26 @@ ___
• **provider**: *`ZeroExProvider`*
-*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:26](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L26)*
+*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:27](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L27)*
## Methods
### executeSwapQuoteOrThrowAsync
-▸ **executeSwapQuoteOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
+▸ **executeSwapQuoteOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
*Implementation of [SwapQuoteConsumerBase](#interface-swapquoteconsumerbase)*
-*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:81](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L81)*
+*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:89](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L89)*
-Given a SwapQuote and desired rate (in takerAsset), attempt to execute the swap.
+Given a SwapQuote and desired rate (in takerAsset), attempt to execute the swap with 0x extension or exchange contract.
**Parameters:**
Name | Type | Default | Description |
------ | ------ | ------ | ------ |
`quote` | [SwapQuote](#swapquote) | - | An object that conforms to SwapQuote. See type definition for more information. |
-`opts` | `Partial` | {} | Options for getting CalldataInfo. See type definition for more information. |
+`opts` | `Partial` | {} | Options for getting CalldataInfo. See type definition for more information. |
**Returns:** *`Promise`*
@@ -109,20 +106,20 @@ ___
### getCalldataOrThrowAsync
-▸ **getCalldataOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
+▸ **getCalldataOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
*Implementation of [SwapQuoteConsumerBase](#interface-swapquoteconsumerbase)*
-*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:53](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L53)*
+*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:61](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L61)*
-Given a SwapQuote, returns 'CalldataInfo' for a 0x exchange call. See type definition of CalldataInfo for more information.
+Given a SwapQuote, returns 'CalldataInfo' for a 0x extesion or exchange call. See type definition of CalldataInfo for more information.
**Parameters:**
Name | Type | Default | Description |
------ | ------ | ------ | ------ |
`quote` | [SwapQuote](#swapquote) | - | An object that conforms to SwapQuote. See type definition for more information. |
-`opts` | `Partial` | {} | Options for getting SmartContractParams. See type definition for more information. |
+`opts` | `Partial` | {} | Options for getting SmartContractParams. See type definition for more information. |
**Returns:** *`Promise`*
@@ -132,14 +129,16 @@ ___
▸ **getOptimalExtensionContractTypeAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
-*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:90](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L90)*
+*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:103](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L103)*
+
+Given a SwapQuote, returns optimal 0x protocol interface (extension or no extension) to perform the swap.
**Parameters:**
-Name | Type | Default |
------- | ------ | ------ |
-`quote` | [SwapQuote](#swapquote) | - |
-`opts` | `Partial` | {} |
+Name | Type | Default | Description |
+------ | ------ | ------ | ------ |
+`quote` | [SwapQuote](#swapquote) | - | An object that conforms to SwapQuote. See type definition for more information. |
+`opts` | `Partial` | {} | Options for getting optimal exteion contract to fill quote. See type definition for more information. |
**Returns:** *`Promise`*
@@ -147,23 +146,40 @@ ___
### getSmartContractParamsOrThrowAsync
-▸ **getSmartContractParamsOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise>`*
+▸ **getSmartContractParamsOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise>`*
*Implementation of [SwapQuoteConsumerBase](#interface-swapquoteconsumerbase)*
-*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:67](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L67)*
+*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:75](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L75)*
-Given a SwapQuote, returns 'SmartContractParamsInfo' for a 0x exchange call. See type definition of SmartContractParamsInfo for more information.
+Given a SwapQuote, returns 'SmartContractParamsInfo' for a 0x extension or exchange call. See type definition of SmartContractParamsInfo for more information.
**Parameters:**
Name | Type | Default | Description |
------ | ------ | ------ | ------ |
`quote` | [SwapQuote](#swapquote) | - | An object that conforms to SwapQuote. See type definition for more information. |
-`opts` | `Partial` | {} | Options for getting SmartContractParams. See type definition for more information. |
+`opts` | `Partial` | {} | Options for getting SmartContractParams. See type definition for more information. |
**Returns:** *`Promise>`*
+___
+
+### `Static` getSwapQuoteConsumer
+
+▸ **getSwapQuoteConsumer**(`supportedProvider`: [SupportedProvider](#supportedprovider), `options`: `Partial`): *[SwapQuoteConsumer](#class-swapquoteconsumer)*
+
+*Defined in [asset-swapper/src/quote_consumers/swap_quote_consumer.ts:34](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts#L34)*
+
+**Parameters:**
+
+Name | Type | Default |
+------ | ------ | ------ |
+`supportedProvider` | [SupportedProvider](#supportedprovider) | - |
+`options` | `Partial` | {} |
+
+**Returns:** *[SwapQuoteConsumer](#class-swapquoteconsumer)*
+
# Class: SwapQuoter
@@ -175,7 +191,7 @@ Name | Type | Default | Description |
\+ **new SwapQuoter**(`supportedProvider`: [SupportedProvider](#supportedprovider), `orderbook`: `Orderbook`, `options`: `Partial`): *[SwapQuoter](#class-swapquoter)*
-*Defined in [asset-swapper/src/swap_quoter.ts:124](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L124)*
+*Defined in [asset-swapper/src/swap_quoter.ts:129](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L129)*
Instantiates a new SwapQuoter instance
@@ -197,7 +213,7 @@ An instance of SwapQuoter
• **expiryBufferMs**: *number*
-*Defined in [asset-swapper/src/swap_quoter.ts:30](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L30)*
+*Defined in [asset-swapper/src/swap_quoter.ts:32](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L32)*
___
@@ -205,7 +221,15 @@ ___
• **orderbook**: *`Orderbook`*
-*Defined in [asset-swapper/src/swap_quoter.ts:29](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L29)*
+*Defined in [asset-swapper/src/swap_quoter.ts:31](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L31)*
+
+___
+
+### permittedOrderFeeTypes
+
+• **permittedOrderFeeTypes**: *`Set`*
+
+*Defined in [asset-swapper/src/swap_quoter.ts:33](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L33)*
___
@@ -213,7 +237,7 @@ ___
• **provider**: *`ZeroExProvider`*
-*Defined in [asset-swapper/src/swap_quoter.ts:28](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L28)*
+*Defined in [asset-swapper/src/swap_quoter.ts:30](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L30)*
## Methods
@@ -221,7 +245,7 @@ ___
▸ **destroyAsync**(): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:396](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L396)*
+*Defined in [asset-swapper/src/swap_quoter.ts:393](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L393)*
Destroys any subscriptions or connections.
@@ -233,7 +257,7 @@ ___
▸ **getAvailableMakerAssetDatasAsync**(`takerAssetData`: string): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:315](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L315)*
+*Defined in [asset-swapper/src/swap_quoter.ts:321](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L321)*
Get the asset data of all assets that are purchaseable with takerAssetData in the order provider passed in at init.
@@ -253,7 +277,7 @@ ___
▸ **getAvailableTakerAssetDatasAsync**(`makerAssetData`: string): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:300](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L300)*
+*Defined in [asset-swapper/src/swap_quoter.ts:306](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L306)*
Get the asset data of all assets that can be used to purchase makerAssetData in the order provider passed in at init.
@@ -269,11 +293,23 @@ An array of asset data strings that can purchase makerAssetData.
___
+### getEtherTokenAssetDataOrThrowAsync
+
+▸ **getEtherTokenAssetDataOrThrowAsync**(): *`Promise`*
+
+*Defined in [asset-swapper/src/swap_quoter.ts:400](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L400)*
+
+Utility function to get assetData for Ether token.
+
+**Returns:** *`Promise`*
+
+___
+
### getLiquidityForMakerTakerAssetDataPairAsync
-▸ **getLiquidityForMakerTakerAssetDataPairAsync**(`makerAssetData`: string, `takerAssetData`: string): *`Promise`*
+▸ **getLiquidityForMakerTakerAssetDataPairAsync**(`makerAssetData`: string, `takerAssetData`: string): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:274](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L274)*
+*Defined in [asset-swapper/src/swap_quoter.ts:281](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L281)*
Returns information about available liquidity for an asset
Does not factor in slippage or fees
@@ -285,9 +321,9 @@ Name | Type | Description |
`makerAssetData` | string | The makerAssetData of the desired asset to swap for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). |
`takerAssetData` | string | The takerAssetData of the asset to swap makerAssetData for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). |
-**Returns:** *`Promise`*
+**Returns:** *`Promise`*
-An object that conforms to LiquidityForAssetData that satisfies the request. See type definition for more information.
+An object that conforms to LiquidityForTakerMakerAssetDataPair that satisfies the request. See type definition for more information.
___
@@ -295,7 +331,7 @@ ___
▸ **getMarketBuySwapQuoteAsync**(`makerTokenAddress`: string, `takerTokenAddress`: string, `makerAssetBuyAmount`: `BigNumber`, `options`: `Partial`): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:208](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L208)*
+*Defined in [asset-swapper/src/swap_quoter.ts:223](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L223)*
Get a `SwapQuote` containing all information relevant to fulfilling a swap between a desired ERC20 token address and ERC20 owned by a provided address.
You can then pass the `SwapQuote` to a `SwapQuoteConsumer` to execute a buy, or process SwapQuote for on-chain consumption.
@@ -319,7 +355,7 @@ ___
▸ **getMarketBuySwapQuoteForAssetDataAsync**(`makerAssetData`: string, `takerAssetData`: string, `makerAssetBuyAmount`: `BigNumber`, `options`: `Partial`): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:183](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L183)*
+*Defined in [asset-swapper/src/swap_quoter.ts:198](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L198)*
Get a `SwapQuote` containing all information relevant to fulfilling a swap between a desired ERC20 token address and ERC20 owned by a provided address.
You can then pass the `SwapQuote` to a `SwapQuoteConsumer` to execute a buy, or process SwapQuote for on-chain consumption.
@@ -343,7 +379,7 @@ ___
▸ **getMarketSellSwapQuoteAsync**(`makerTokenAddress`: string, `takerTokenAddress`: string, `takerAssetSellAmount`: `BigNumber`, `options`: `Partial`): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:242](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L242)*
+*Defined in [asset-swapper/src/swap_quoter.ts:253](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L253)*
Get a `SwapQuote` containing all information relevant to fulfilling a swap between a desired ERC20 token address and ERC20 owned by a provided address.
You can then pass the `SwapQuote` to a `SwapQuoteConsumer` to execute a buy, or process SwapQuote for on-chain consumption.
@@ -367,7 +403,7 @@ ___
▸ **getMarketSellSwapQuoteForAssetDataAsync**(`makerAssetData`: string, `takerAssetData`: string, `takerAssetSellAmount`: `BigNumber`, `options`: `Partial`): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:157](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L157)*
+*Defined in [asset-swapper/src/swap_quoter.ts:172](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L172)*
Get a `SwapQuote` containing all information relevant to fulfilling a swap between a desired ERC20 token address and ERC20 owned by a provided address.
You can then pass the `SwapQuote` to a `SwapQuoteConsumer` to execute a buy, or process SwapQuote for on-chain consumption.
@@ -387,13 +423,13 @@ An object that conforms to SwapQuote that satisfies the request. See type defini
___
-### getOrdersAndFillableAmountsAsync
+### getPrunedSignedOrdersAsync
-▸ **getOrdersAndFillableAmountsAsync**(`makerAssetData`: string, `takerAssetData`: string): *`Promise`*
+▸ **getPrunedSignedOrdersAsync**(`makerAssetData`: string, `takerAssetData`: string): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:347](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L347)*
+*Defined in [asset-swapper/src/swap_quoter.ts:355](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L355)*
-Grab orders from the map, if there is a miss or it is time to refresh, fetch and process the orders
+Grab orders from the order provider, prunes for valid orders with provided OrderPruner options
**Parameters:**
@@ -402,15 +438,15 @@ Name | Type | Description |
`makerAssetData` | string | The makerAssetData of the desired asset to swap for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). |
`takerAssetData` | string | The takerAssetData of the asset to swap makerAssetData for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). |
-**Returns:** *`Promise`*
+**Returns:** *`Promise`*
___
-### isTakerAddressAllowanceEnoughForBestAndWorstQuoteInfoAsync
+### isSwapQuoteFillableByTakerAddressAsync
-▸ **isTakerAddressAllowanceEnoughForBestAndWorstQuoteInfoAsync**(`swapQuote`: [SwapQuote](#swapquote), `takerAddress`: string): *`Promise<[boolean, boolean]>`*
+▸ **isSwapQuoteFillableByTakerAddressAsync**(`swapQuote`: [SwapQuote](#swapquote), `takerAddress`: string): *`Promise<[boolean, boolean]>`*
-*Defined in [asset-swapper/src/swap_quoter.ts:378](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L378)*
+*Defined in [asset-swapper/src/swap_quoter.ts:376](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L376)*
Util function to check if takerAddress's allowance is enough for 0x exchange contracts to conduct the swap specified by the swapQuote.
@@ -429,16 +465,16 @@ ___
▸ **isTakerMakerAssetDataPairAvailableAsync**(`makerAssetData`: string, `takerAssetData`: string): *`Promise`*
-*Defined in [asset-swapper/src/swap_quoter.ts:330](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L330)*
+*Defined in [asset-swapper/src/swap_quoter.ts:338](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L338)*
Validates the taker + maker asset pair is available from the order provider provided to `SwapQuote`.
**Parameters:**
-Name | Type |
------- | ------ |
-`makerAssetData` | string |
-`takerAssetData` | string |
+Name | Type | Description |
+------ | ------ | ------ |
+`makerAssetData` | string | The makerAssetData of the desired asset to swap for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). |
+`takerAssetData` | string | The takerAssetData of the asset to swap makerAssetData for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). |
**Returns:** *`Promise`*
@@ -450,7 +486,7 @@ ___
▸ **getSwapQuoterForMeshEndpoint**(`supportedProvider`: [SupportedProvider](#supportedprovider), `meshEndpoint`: string, `options`: `Partial`): *[SwapQuoter](#class-swapquoter)*
-*Defined in [asset-swapper/src/swap_quoter.ts:111](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L111)*
+*Defined in [asset-swapper/src/swap_quoter.ts:116](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L116)*
Instantiates a new SwapQuoter instance given a 0x Mesh endpoint. This pulls all available liquidity stored in Mesh
@@ -472,7 +508,7 @@ ___
▸ **getSwapQuoterForProvidedOrders**(`supportedProvider`: [SupportedProvider](#supportedprovider), `orders`: `SignedOrder`[], `options`: `Partial`): *[SwapQuoter](#class-swapquoter)*
-*Defined in [asset-swapper/src/swap_quoter.ts:41](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L41)*
+*Defined in [asset-swapper/src/swap_quoter.ts:44](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L44)*
Instantiates a new SwapQuoter instance given existing liquidity in the form of orders and feeOrders.
@@ -494,7 +530,7 @@ ___
▸ **getSwapQuoterForStandardRelayerAPIUrl**(`supportedProvider`: [SupportedProvider](#supportedprovider), `sraApiUrl`: string, `options`: `Partial`): *[SwapQuoter](#class-swapquoter)*
-*Defined in [asset-swapper/src/swap_quoter.ts:61](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L61)*
+*Defined in [asset-swapper/src/swap_quoter.ts:64](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L64)*
Instantiates a new SwapQuoter instance given a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) endpoint
@@ -516,7 +552,7 @@ ___
▸ **getSwapQuoterForStandardRelayerAPIWebsocket**(`supportedProvider`: [SupportedProvider](#supportedprovider), `sraApiUrl`: string, `sraWebsocketAPIUrl`: string, `options`: `Partial`): *[SwapQuoter](#class-swapquoter)*
-*Defined in [asset-swapper/src/swap_quoter.ts:87](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/swap_quoter.ts#L87)*
+*Defined in [asset-swapper/src/swap_quoter.ts:91](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/swap_quoter.ts#L91)*
Instantiates a new SwapQuoter instance given a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) endpoint
and a websocket endpoint. This is more effecient than `getSwapQuoterForStandardRelayerAPIUrl` when requesting multiple quotes.
@@ -545,7 +581,7 @@ An instance of SwapQuoter
\+ **new BaseOrderProvider**(`orderStore`: [OrderStore](_orderbook_src_order_store_.orderstore.md)): *[BaseOrderProvider](#class-baseorderprovider)*
-*Defined in [orderbook/src/order_provider/base_order_provider.ts:12](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_provider/base_order_provider.ts#L12)*
+*Defined in [orderbook/src/order_provider/base_order_provider.ts:12](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_provider/base_order_provider.ts#L12)*
**Parameters:**
@@ -561,7 +597,7 @@ Name | Type |
• **_orderStore**: *[OrderStore](#class-orderstore)*
-*Defined in [orderbook/src/order_provider/base_order_provider.ts:12](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_provider/base_order_provider.ts#L12)*
+*Defined in [orderbook/src/order_provider/base_order_provider.ts:12](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_provider/base_order_provider.ts#L12)*
## Methods
@@ -569,7 +605,7 @@ Name | Type |
▸ **addOrdersAsync**(`orders`: `SignedOrder`[]): *`Promise`*
-*Defined in [orderbook/src/order_provider/base_order_provider.ts:27](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_provider/base_order_provider.ts#L27)*
+*Defined in [orderbook/src/order_provider/base_order_provider.ts:27](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_provider/base_order_provider.ts#L27)*
**Parameters:**
@@ -585,7 +621,7 @@ ___
▸ **createSubscriptionForAssetPairAsync**(`makerAssetData`: string, `takerAssetData`: string): *`Promise`*
-*Defined in [orderbook/src/order_provider/base_order_provider.ts:18](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_provider/base_order_provider.ts#L18)*
+*Defined in [orderbook/src/order_provider/base_order_provider.ts:18](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_provider/base_order_provider.ts#L18)*
**Parameters:**
@@ -602,7 +638,7 @@ ___
▸ **destroyAsync**(): *`Promise`*
-*Defined in [orderbook/src/order_provider/base_order_provider.ts:25](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_provider/base_order_provider.ts#L25)*
+*Defined in [orderbook/src/order_provider/base_order_provider.ts:25](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_provider/base_order_provider.ts#L25)*
**Returns:** *`Promise`*
@@ -612,7 +648,7 @@ ___
▸ **getAvailableAssetDatasAsync**(): *`Promise`*
-*Defined in [orderbook/src/order_provider/base_order_provider.ts:23](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_provider/base_order_provider.ts#L23)*
+*Defined in [orderbook/src/order_provider/base_order_provider.ts:23](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_provider/base_order_provider.ts#L23)*
**Returns:** *`Promise`*
@@ -625,19 +661,25 @@ ___
-\+ **new OrderSet**(): *[OrderSet](#class-orderset)*
+\+ **new OrderSet**(`orders`: `APIOrder`[]): *[OrderSet](#class-orderset)*
-*Defined in [orderbook/src/order_set.ts:6](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L6)*
+*Defined in [orderbook/src/order_set.ts:6](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L6)*
+
+**Parameters:**
+
+Name | Type | Default |
+------ | ------ | ------ |
+`orders` | `APIOrder`[] | [] |
**Returns:** *[OrderSet](#class-orderset)*
## Methods
-### addAsync
+### add
-▸ **addAsync**(`item`: `APIOrder`): *`Promise`*
+▸ **add**(`item`: `APIOrder`): *void*
-*Defined in [orderbook/src/order_set.ts:16](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L16)*
+*Defined in [orderbook/src/order_set.ts:19](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L19)*
**Parameters:**
@@ -645,15 +687,15 @@ Name | Type |
------ | ------ |
`item` | `APIOrder` |
-**Returns:** *`Promise`*
+**Returns:** *void*
___
-### addManyAsync
+### addMany
-▸ **addManyAsync**(`items`: `APIOrder`[]): *`Promise`*
+▸ **addMany**(`items`: `APIOrder`[]): *void*
-*Defined in [orderbook/src/order_set.ts:22](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L22)*
+*Defined in [orderbook/src/order_set.ts:25](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L25)*
**Parameters:**
@@ -661,15 +703,15 @@ Name | Type |
------ | ------ |
`items` | `APIOrder`[] |
-**Returns:** *`Promise`*
+**Returns:** *void*
___
-### deleteAsync
+### delete
-▸ **deleteAsync**(`item`: `APIOrder`): *`Promise`*
+▸ **delete**(`item`: `APIOrder`): *boolean*
-*Defined in [orderbook/src/order_set.ts:54](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L54)*
+*Defined in [orderbook/src/order_set.ts:57](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L57)*
**Parameters:**
@@ -677,15 +719,15 @@ Name | Type |
------ | ------ |
`item` | `APIOrder` |
-**Returns:** *`Promise`*
+**Returns:** *boolean*
___
-### deleteManyAsync
+### deleteMany
-▸ **deleteManyAsync**(`items`: `APIOrder`[]): *`Promise`*
+▸ **deleteMany**(`items`: `APIOrder`[]): *void*
-*Defined in [orderbook/src/order_set.ts:58](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L58)*
+*Defined in [orderbook/src/order_set.ts:61](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L61)*
**Parameters:**
@@ -693,15 +735,15 @@ Name | Type |
------ | ------ |
`items` | `APIOrder`[] |
-**Returns:** *`Promise`*
+**Returns:** *void*
___
-### diffAsync
+### diff
-▸ **diffAsync**(`other`: [OrderSet](#class-orderset)): *`Promise`*
+▸ **diff**(`other`: [OrderSet](#class-orderset)): *object*
-*Defined in [orderbook/src/order_set.ts:32](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L32)*
+*Defined in [orderbook/src/order_set.ts:35](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L35)*
**Parameters:**
@@ -709,15 +751,15 @@ Name | Type |
------ | ------ |
`other` | [OrderSet](#class-orderset) |
-**Returns:** *`Promise`*
+**Returns:** *object*
___
-### hasAsync
+### has
-▸ **hasAsync**(`order`: `APIOrder`): *`Promise`*
+▸ **has**(`order`: `APIOrder`): *boolean*
-*Defined in [orderbook/src/order_set.ts:28](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L28)*
+*Defined in [orderbook/src/order_set.ts:31](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L31)*
**Parameters:**
@@ -725,7 +767,7 @@ Name | Type |
------ | ------ |
`order` | `APIOrder` |
-**Returns:** *`Promise`*
+**Returns:** *boolean*
___
@@ -733,7 +775,7 @@ ___
▸ **size**(): *number*
-*Defined in [orderbook/src/order_set.ts:12](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L12)*
+*Defined in [orderbook/src/order_set.ts:15](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L15)*
**Returns:** *number*
@@ -743,7 +785,7 @@ ___
▸ **values**(): *`IterableIterator`*
-*Defined in [orderbook/src/order_set.ts:50](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_set.ts#L50)*
+*Defined in [orderbook/src/order_set.ts:53](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_set.ts#L53)*
**Returns:** *`IterableIterator`*
@@ -758,7 +800,7 @@ ___
▸ **getOrderSetForAssetPair**(`assetPairKey`: string): *[OrderSet](#class-orderset)*
-*Defined in [orderbook/src/order_store.ts:19](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_store.ts#L19)*
+*Defined in [orderbook/src/order_store.ts:19](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_store.ts#L19)*
**Parameters:**
@@ -774,7 +816,7 @@ ___
▸ **getOrderSetForAssets**(`makerAssetData`: string, `takerAssetData`: string): *[OrderSet](#class-orderset)*
-*Defined in [orderbook/src/order_store.ts:15](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_store.ts#L15)*
+*Defined in [orderbook/src/order_store.ts:15](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_store.ts#L15)*
**Parameters:**
@@ -791,7 +833,7 @@ ___
▸ **has**(`assetPairKey`: string): *boolean*
-*Defined in [orderbook/src/order_store.ts:34](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_store.ts#L34)*
+*Defined in [orderbook/src/order_store.ts:34](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_store.ts#L34)*
**Parameters:**
@@ -807,17 +849,17 @@ ___
▸ **keys**(): *`IterableIterator`*
-*Defined in [orderbook/src/order_store.ts:40](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_store.ts#L40)*
+*Defined in [orderbook/src/order_store.ts:40](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_store.ts#L40)*
**Returns:** *`IterableIterator`*
___
-### updateAsync
+### update
-▸ **updateAsync**(`addedRemoved`: [AddedRemovedOrders](#interface-addedremovedorders)): *`Promise`*
+▸ **update**(`addedRemoved`: [AddedRemovedOrders](#interface-addedremovedorders)): *void*
-*Defined in [orderbook/src/order_store.ts:28](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_store.ts#L28)*
+*Defined in [orderbook/src/order_store.ts:28](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_store.ts#L28)*
**Parameters:**
@@ -825,7 +867,7 @@ Name | Type |
------ | ------ |
`addedRemoved` | [AddedRemovedOrders](#interface-addedremovedorders) |
-**Returns:** *`Promise`*
+**Returns:** *void*
___
@@ -833,7 +875,7 @@ ___
▸ **values**(`assetPairKey`: string): *`APIOrder`[]*
-*Defined in [orderbook/src/order_store.ts:37](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_store.ts#L37)*
+*Defined in [orderbook/src/order_store.ts:37](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_store.ts#L37)*
**Parameters:**
@@ -849,7 +891,7 @@ ___
▸ **assetPairKeyToAssets**(`assetPairKey`: string): *string[]*
-*Defined in [orderbook/src/order_store.ts:12](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_store.ts#L12)*
+*Defined in [orderbook/src/order_store.ts:12](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_store.ts#L12)*
**Parameters:**
@@ -865,7 +907,7 @@ ___
▸ **getKeyForAssetPair**(`makerAssetData`: string, `takerAssetData`: string): *string*
-*Defined in [orderbook/src/order_store.ts:9](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_store.ts#L9)*
+*Defined in [orderbook/src/order_store.ts:9](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_store.ts#L9)*
**Parameters:**
@@ -887,7 +929,7 @@ Name | Type |
\+ **new Orderbook**(`orderProvider`: [BaseOrderProvider](_orderbook_src_order_provider_base_order_provider_.baseorderprovider.md), `orderStore`: [OrderStore](_orderbook_src_order_store_.orderstore.md)): *[Orderbook](#class-orderbook)*
-*Defined in [orderbook/src/orderbook.ts:55](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L55)*
+*Defined in [orderbook/src/orderbook.ts:55](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L55)*
Creates an Orderbook with the order provider. All order updates are stored
in the `OrderStore`.
@@ -907,7 +949,7 @@ Name | Type | Description |
▸ **addOrdersAsync**(`orders`: `SignedOrder`[]): *`Promise`*
-*Defined in [orderbook/src/orderbook.ts:98](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L98)*
+*Defined in [orderbook/src/orderbook.ts:98](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L98)*
Adds the orders to the Order Provider. All accepted orders will be returned
and rejected orders will be returned with an message indicating a reason for its rejection
@@ -926,7 +968,7 @@ ___
▸ **destroyAsync**(): *`Promise`*
-*Defined in [orderbook/src/orderbook.ts:104](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L104)*
+*Defined in [orderbook/src/orderbook.ts:104](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L104)*
Destroys any subscriptions or connections.
@@ -938,7 +980,7 @@ ___
▸ **getAvailableAssetDatasAsync**(): *`Promise`*
-*Defined in [orderbook/src/orderbook.ts:90](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L90)*
+*Defined in [orderbook/src/orderbook.ts:90](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L90)*
Returns all of the Available Asset Pairs for the provided Order Provider.
@@ -950,7 +992,7 @@ ___
▸ **getOrdersAsync**(`makerAssetData`: string, `takerAssetData`: string): *`Promise`*
-*Defined in [orderbook/src/orderbook.ts:75](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L75)*
+*Defined in [orderbook/src/orderbook.ts:75](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L75)*
Returns all orders where the order.makerAssetData == makerAssetData and
order.takerAssetData == takerAssetData. This pair is then subscribed to
@@ -973,7 +1015,7 @@ ___
▸ **getOrderbookForMeshProvider**(`opts`: [MeshOrderProviderOpts](#interface-meshorderprovideropts)): *[Orderbook](#class-orderbook)*
-*Defined in [orderbook/src/orderbook.ts:52](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L52)*
+*Defined in [orderbook/src/orderbook.ts:52](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L52)*
Creates an Orderbook with a Mesh Order Provider. This Provider fetches ALL orders
and subscribes to updates on ALL orders.
@@ -992,7 +1034,7 @@ ___
▸ **getOrderbookForPollingProvider**(`opts`: [SRAPollingOrderProviderOpts](#interface-srapollingorderprovideropts)): *[Orderbook](#class-orderbook)*
-*Defined in [orderbook/src/orderbook.ts:43](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L43)*
+*Defined in [orderbook/src/orderbook.ts:43](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L43)*
Creates an Orderbook with SRA Polling Provider. This Provider simply polls every interval.
@@ -1010,7 +1052,7 @@ ___
▸ **getOrderbookForProvidedOrders**(`orders`: `SignedOrder`[]): *[Orderbook](#class-orderbook)*
-*Defined in [orderbook/src/orderbook.ts:26](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L26)*
+*Defined in [orderbook/src/orderbook.ts:26](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L26)*
Creates an Orderbook with the provided orders. This provider simply stores the
orders and allows querying. No validation or subscriptions occur.
@@ -1029,7 +1071,7 @@ ___
▸ **getOrderbookForWebsocketProvider**(`opts`: [SRAWebsocketOrderProviderOpts](#interface-srawebsocketorderprovideropts)): *[Orderbook](#class-orderbook)*
-*Defined in [orderbook/src/orderbook.ts:35](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/orderbook.ts#L35)*
+*Defined in [orderbook/src/orderbook.ts:35](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/orderbook.ts#L35)*
Creates an Orderbook with the SRA Websocket Provider. This Provider fetches orders via
the SRA http endpoint and then subscribes to the asset pair for future updates.
@@ -1055,7 +1097,7 @@ Represents the varying smart contracts that can consume a valid swap quote
• **Forwarder**: = "FORWARDER"
-*Defined in [asset-swapper/src/types.ts:88](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L88)*
+*Defined in [asset-swapper/src/types.ts:106](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L106)*
___
@@ -1063,12 +1105,16 @@ ___
• **None**: = "NONE"
-*Defined in [asset-swapper/src/types.ts:89](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L89)*
+*Defined in [asset-swapper/src/types.ts:107](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L107)*
+
+
+
+
# Enumeration: SwapQuoterError
Possible error messages thrown by an SwapQuoter instance or associated static methods.
@@ -1080,15 +1126,7 @@ Possible error messages thrown by an SwapQuoter instance or associated static me
• **AssetUnavailable**: = "ASSET_UNAVAILABLE"
-*Defined in [asset-swapper/src/types.ts:303](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L303)*
-
-___
-
-### FeeAssetUnavailable
-
-• **FeeAssetUnavailable**: = "FEE_ASSET_UNAVAILABLE"
-
-*Defined in [asset-swapper/src/types.ts:304](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L304)*
+*Defined in [asset-swapper/src/types.ts:298](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L298)*
___
@@ -1096,23 +1134,7 @@ ___
• **InsufficientAssetLiquidity**: = "INSUFFICIENT_ASSET_LIQUIDITY"
-*Defined in [asset-swapper/src/types.ts:300](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L300)*
-
-___
-
-### InsufficientZrxLiquidity
-
-• **InsufficientZrxLiquidity**: = "INSUFFICIENT_ZRX_LIQUIDITY"
-
-*Defined in [asset-swapper/src/types.ts:301](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L301)*
-
-___
-
-### InvalidOrderProviderResponse
-
-• **InvalidOrderProviderResponse**: = "INVALID_ORDER_PROVIDER_RESPONSE"
-
-*Defined in [asset-swapper/src/types.ts:302](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L302)*
+*Defined in [asset-swapper/src/types.ts:297](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L297)*
___
@@ -1120,15 +1142,15 @@ ___
• **NoEtherTokenContractFound**: = "NO_ETHER_TOKEN_CONTRACT_FOUND"
-*Defined in [asset-swapper/src/types.ts:297](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L297)*
+*Defined in [asset-swapper/src/types.ts:295](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L295)*
___
-### NoZrxTokenContractFound
+### NoGasPriceProvidedOrEstimated
-• **NoZrxTokenContractFound**: = "NO_ZRX_TOKEN_CONTRACT_FOUND"
+• **NoGasPriceProvidedOrEstimated**: = "NO_GAS_PRICE_PROVIDED_OR_ESTIMATED"
-*Defined in [asset-swapper/src/types.ts:298](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L298)*
+*Defined in [asset-swapper/src/types.ts:299](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L299)*
___
@@ -1136,7 +1158,7 @@ ___
• **StandardRelayerApiError**: = "STANDARD_RELAYER_API_ERROR"
-*Defined in [asset-swapper/src/types.ts:299](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L299)*
+*Defined in [asset-swapper/src/types.ts:296](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L296)*
@@ -1169,8 +1191,6 @@ ___
-
-
@@ -1182,7 +1202,7 @@ Represents the metadata to call a smart contract with calldata.
calldataHexString: The hexstring of the calldata.
methodAbi: The ABI of the smart contract method to call.
toAddress: The contract address to call.
-ethAmount: If provided, the eth amount in wei to send with the smart contract call.
+ethAmount: The eth amount in wei to send with the smart contract call.
## Properties
@@ -1191,15 +1211,15 @@ ethAmount: If provided, the eth amount in wei to send with the smart contract ca
• **calldataHexString**: *string*
-*Defined in [asset-swapper/src/types.ts:37](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L37)*
+*Defined in [asset-swapper/src/types.ts:55](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L55)*
___
-### `Optional` ethAmount
+### ethAmount
-• **ethAmount**? : *`BigNumber`*
+• **ethAmount**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:40](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L40)*
+*Defined in [asset-swapper/src/types.ts:58](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L58)*
___
@@ -1207,7 +1227,7 @@ ___
• **methodAbi**: *`MethodAbi`*
-*Defined in [asset-swapper/src/types.ts:38](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L38)*
+*Defined in [asset-swapper/src/types.ts:56](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L56)*
___
@@ -1215,7 +1235,7 @@ ___
• **toAddress**: *string*
-*Defined in [asset-swapper/src/types.ts:39](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L39)*
+*Defined in [asset-swapper/src/types.ts:57](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L57)*
@@ -1229,104 +1249,8 @@ ___
-# Interface: ForwarderSwapQuoteExecutionOpts
-## Properties
-
-### `Optional` ethAmount
-
-• **ethAmount**? : *`BigNumber`*
-
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[ethAmount](#optional-ethamount)*
-
-*Defined in [asset-swapper/src/types.ts:179](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L179)*
-
-___
-
-### feePercentage
-
-• **feePercentage**: *number*
-
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[feePercentage](#feepercentage)*
-
-*Defined in [asset-swapper/src/types.ts:177](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L177)*
-
-___
-
-### feeRecipient
-
-• **feeRecipient**: *string*
-
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[feeRecipient](#feerecipient)*
-
-*Defined in [asset-swapper/src/types.ts:178](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L178)*
-
-___
-
-### `Optional` gasLimit
-
-• **gasLimit**? : *undefined | number*
-
-*Inherited from [SwapQuoteExecutionOptsBase](#interface-swapquoteexecutionoptsbase).[gasLimit](#optional-gaslimit)*
-
-*Defined in [asset-swapper/src/types.ts:167](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L167)*
-
-___
-
-### `Optional` gasPrice
-
-• **gasPrice**? : *`BigNumber`*
-
-*Inherited from [SwapQuoteExecutionOptsBase](#interface-swapquoteexecutionoptsbase).[gasPrice](#optional-gasprice)*
-
-*Defined in [asset-swapper/src/types.ts:168](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L168)*
-
-___
-
-### `Optional` takerAddress
-
-• **takerAddress**? : *undefined | string*
-
-*Inherited from [SwapQuoteExecutionOptsBase](#interface-swapquoteexecutionoptsbase).[takerAddress](#optional-takeraddress)*
-
-*Defined in [asset-swapper/src/types.ts:166](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L166)*
-
-
-
-# Interface: ForwarderSwapQuoteGetOutputOpts
-
-feePercentage: percentage (up to 5%) of the taker asset paid to feeRecipient
-feeRecipient: address of the receiver of the feePercentage of taker asset
-ethAmount: The amount of eth (in Wei) sent to the forwarder contract.
-
-
-## Properties
-
-### `Optional` ethAmount
-
-• **ethAmount**? : *`BigNumber`*
-
-*Defined in [asset-swapper/src/types.ts:179](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L179)*
-
-___
-
-### feePercentage
-
-• **feePercentage**: *number*
-
-*Defined in [asset-swapper/src/types.ts:177](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L177)*
-
-___
-
-### feeRecipient
-
-• **feeRecipient**: *string*
-
-*Defined in [asset-swapper/src/types.ts:178](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L178)*
-
-
-
# Interface: GetExtensionContractTypeOpts
@@ -1336,7 +1260,7 @@ ___
• **ethAmount**? : *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:186](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L186)*
+*Defined in [asset-swapper/src/types.ts:209](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L209)*
___
@@ -1344,30 +1268,30 @@ ___
• **takerAddress**? : *undefined | string*
-*Defined in [asset-swapper/src/types.ts:185](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L185)*
+*Defined in [asset-swapper/src/types.ts:208](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L208)*
-# Interface: LiquidityForAssetData
+# Interface: LiquidityForTakerMakerAssetDataPair
-Represents available liquidity for a given assetData
+Represents available liquidity for a given assetData.
## Properties
-### makerTokensAvailableInBaseUnits
+### makerAssetAvailableInBaseUnits
-• **makerTokensAvailableInBaseUnits**: *`BigNumber`*
+• **makerAssetAvailableInBaseUnits**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:320](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L320)*
+*Defined in [asset-swapper/src/types.ts:306](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L306)*
___
-### takerTokensAvailableInBaseUnits
+### takerAssetAvailableInBaseUnits
-• **takerTokensAvailableInBaseUnits**: *`BigNumber`*
+• **takerAssetAvailableInBaseUnits**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:321](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L321)*
+*Defined in [asset-swapper/src/types.ts:307](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L307)*
@@ -1385,17 +1309,7 @@ type: Specified MarketOperation the SwapQuote is provided for
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[bestCaseQuoteInfo](#bestcasequoteinfo)*
-*Defined in [asset-swapper/src/types.ts:217](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L217)*
-
-___
-
-### feeOrders
-
-• **feeOrders**: *`SignedOrder`[]*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[feeOrders](#feeorders)*
-
-*Defined in [asset-swapper/src/types.ts:216](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L216)*
+*Defined in [asset-swapper/src/types.ts:223](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L223)*
___
@@ -1405,7 +1319,7 @@ ___
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[makerAssetData](#makerassetdata)*
-*Defined in [asset-swapper/src/types.ts:214](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L214)*
+*Defined in [asset-swapper/src/types.ts:221](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L221)*
___
@@ -1413,7 +1327,7 @@ ___
• **makerAssetFillAmount**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:235](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L235)*
+*Defined in [asset-swapper/src/types.ts:241](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L241)*
___
@@ -1423,7 +1337,7 @@ ___
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[orders](#orders)*
-*Defined in [asset-swapper/src/types.ts:215](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L215)*
+*Defined in [asset-swapper/src/types.ts:222](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L222)*
___
@@ -1433,15 +1347,15 @@ ___
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[takerAssetData](#takerassetdata)*
-*Defined in [asset-swapper/src/types.ts:213](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L213)*
+*Defined in [asset-swapper/src/types.ts:220](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L220)*
___
### type
-• **type**: *`Buy`*
+• **type**: *[Buy](#buy)*
-*Defined in [asset-swapper/src/types.ts:236](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L236)*
+*Defined in [asset-swapper/src/types.ts:242](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L242)*
___
@@ -1451,102 +1365,7 @@ ___
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[worstCaseQuoteInfo](#worstcasequoteinfo)*
-*Defined in [asset-swapper/src/types.ts:218](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L218)*
-
-
-
-# Interface: MarketBuySwapQuoteWithAffiliateFee
-
-
-## Properties
-
-### bestCaseQuoteInfo
-
-• **bestCaseQuoteInfo**: *[SwapQuoteInfo](#class-swapquoteinfo)*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[bestCaseQuoteInfo](#bestcasequoteinfo)*
-
-*Defined in [asset-swapper/src/types.ts:217](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L217)*
-
-___
-
-### feeOrders
-
-• **feeOrders**: *`SignedOrder`[]*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[feeOrders](#feeorders)*
-
-*Defined in [asset-swapper/src/types.ts:216](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L216)*
-
-___
-
-### feePercentage
-
-• **feePercentage**: *number*
-
-*Inherited from [SwapQuoteWithAffiliateFeeBase](#interface-swapquotewithaffiliatefeebase).[feePercentage](#feepercentage)*
-
-*Defined in [asset-swapper/src/types.ts:240](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L240)*
-
-___
-
-### makerAssetData
-
-• **makerAssetData**: *string*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[makerAssetData](#makerassetdata)*
-
-*Defined in [asset-swapper/src/types.ts:214](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L214)*
-
-___
-
-### makerAssetFillAmount
-
-• **makerAssetFillAmount**: *`BigNumber`*
-
-*Inherited from [MarketBuySwapQuote](#interface-marketbuyswapquote).[makerAssetFillAmount](#makerassetfillamount)*
-
-*Defined in [asset-swapper/src/types.ts:235](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L235)*
-
-___
-
-### orders
-
-• **orders**: *`SignedOrder`[]*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[orders](#orders)*
-
-*Defined in [asset-swapper/src/types.ts:215](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L215)*
-
-___
-
-### takerAssetData
-
-• **takerAssetData**: *string*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[takerAssetData](#takerassetdata)*
-
-*Defined in [asset-swapper/src/types.ts:213](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L213)*
-
-___
-
-### type
-
-• **type**: *`Buy`*
-
-*Inherited from [MarketBuySwapQuote](#interface-marketbuyswapquote).[type](#type)*
-
-*Defined in [asset-swapper/src/types.ts:236](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L236)*
-
-___
-
-### worstCaseQuoteInfo
-
-• **worstCaseQuoteInfo**: *[SwapQuoteInfo](#class-swapquoteinfo)*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[worstCaseQuoteInfo](#worstcasequoteinfo)*
-
-*Defined in [asset-swapper/src/types.ts:218](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L218)*
+*Defined in [asset-swapper/src/types.ts:224](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L224)*
@@ -1564,17 +1383,7 @@ type: Specified MarketOperation the SwapQuote is provided for
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[bestCaseQuoteInfo](#bestcasequoteinfo)*
-*Defined in [asset-swapper/src/types.ts:217](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L217)*
-
-___
-
-### feeOrders
-
-• **feeOrders**: *`SignedOrder`[]*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[feeOrders](#feeorders)*
-
-*Defined in [asset-swapper/src/types.ts:216](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L216)*
+*Defined in [asset-swapper/src/types.ts:223](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L223)*
___
@@ -1584,7 +1393,7 @@ ___
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[makerAssetData](#makerassetdata)*
-*Defined in [asset-swapper/src/types.ts:214](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L214)*
+*Defined in [asset-swapper/src/types.ts:221](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L221)*
___
@@ -1594,7 +1403,7 @@ ___
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[orders](#orders)*
-*Defined in [asset-swapper/src/types.ts:215](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L215)*
+*Defined in [asset-swapper/src/types.ts:222](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L222)*
___
@@ -1604,7 +1413,7 @@ ___
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[takerAssetData](#takerassetdata)*
-*Defined in [asset-swapper/src/types.ts:213](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L213)*
+*Defined in [asset-swapper/src/types.ts:220](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L220)*
___
@@ -1612,15 +1421,15 @@ ___
• **takerAssetFillAmount**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:226](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L226)*
+*Defined in [asset-swapper/src/types.ts:232](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L232)*
___
### type
-• **type**: *`Sell`*
+• **type**: *[Sell](#sell)*
-*Defined in [asset-swapper/src/types.ts:227](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L227)*
+*Defined in [asset-swapper/src/types.ts:233](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L233)*
___
@@ -1630,42 +1439,106 @@ ___
*Inherited from [SwapQuoteBase](#interface-swapquotebase).[worstCaseQuoteInfo](#worstcasequoteinfo)*
-*Defined in [asset-swapper/src/types.ts:218](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L218)*
+*Defined in [asset-swapper/src/types.ts:224](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L224)*
-# Interface: MarketSellSwapQuoteWithAffiliateFee
+
+
+
+
+
+
+# Interface: PrunedSignedOrder
+
+fillableMakerAssetAmount: Amount of makerAsset that is fillable
+fillableTakerAssetAmount: Amount of takerAsset that is fillable
+fillableTakerFeeAmount: Amount of takerFee paid to fill fillableTakerAssetAmount
## Properties
-### bestCaseQuoteInfo
+### chainId
-• **bestCaseQuoteInfo**: *[SwapQuoteInfo](#class-swapquoteinfo)*
+• **chainId**: *number*
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[bestCaseQuoteInfo](#bestcasequoteinfo)*
-*Defined in [asset-swapper/src/types.ts:217](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L217)*
+
+Defined in types/lib/index.d.ts:4
___
-### feeOrders
+### exchangeAddress
-• **feeOrders**: *`SignedOrder`[]*
+• **exchangeAddress**: *string*
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[feeOrders](#feeorders)*
-*Defined in [asset-swapper/src/types.ts:216](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L216)*
+
+Defined in types/lib/index.d.ts:5
___
-### feePercentage
+### expirationTimeSeconds
-• **feePercentage**: *number*
+• **expirationTimeSeconds**: *`BigNumber`*
-*Inherited from [SwapQuoteWithAffiliateFeeBase](#interface-swapquotewithaffiliatefeebase).[feePercentage](#feepercentage)*
-*Defined in [asset-swapper/src/types.ts:240](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L240)*
+
+Defined in types/lib/index.d.ts:14
+
+___
+
+### feeRecipientAddress
+
+• **feeRecipientAddress**: *string*
+
+
+
+Defined in types/lib/index.d.ts:8
+
+___
+
+### fillableMakerAssetAmount
+
+• **fillableMakerAssetAmount**: *`BigNumber`*
+
+*Defined in [asset-swapper/src/types.ts:42](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L42)*
+
+___
+
+### fillableTakerAssetAmount
+
+• **fillableTakerAssetAmount**: *`BigNumber`*
+
+*Defined in [asset-swapper/src/types.ts:43](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L43)*
+
+___
+
+### fillableTakerFeeAmount
+
+• **fillableTakerFeeAmount**: *`BigNumber`*
+
+*Defined in [asset-swapper/src/types.ts:44](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L44)*
+
+___
+
+### makerAddress
+
+• **makerAddress**: *string*
+
+
+
+Defined in types/lib/index.d.ts:6
+
+___
+
+### makerAssetAmount
+
+• **makerAssetAmount**: *`BigNumber`*
+
+
+
+Defined in types/lib/index.d.ts:10
___
@@ -1673,19 +1546,79 @@ ___
• **makerAssetData**: *string*
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[makerAssetData](#makerassetdata)*
-*Defined in [asset-swapper/src/types.ts:214](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L214)*
+
+Defined in types/lib/index.d.ts:16
___
-### orders
+### makerFee
-• **orders**: *`SignedOrder`[]*
+• **makerFee**: *`BigNumber`*
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[orders](#orders)*
-*Defined in [asset-swapper/src/types.ts:215](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L215)*
+
+Defined in types/lib/index.d.ts:12
+
+___
+
+### makerFeeAssetData
+
+• **makerFeeAssetData**: *string*
+
+
+
+Defined in types/lib/index.d.ts:18
+
+___
+
+### salt
+
+• **salt**: *`BigNumber`*
+
+
+
+Defined in types/lib/index.d.ts:15
+
+___
+
+### senderAddress
+
+• **senderAddress**: *string*
+
+
+
+Defined in types/lib/index.d.ts:9
+
+___
+
+### signature
+
+• **signature**: *string*
+
+
+
+Defined in types/lib/index.d.ts:22
+
+___
+
+### takerAddress
+
+• **takerAddress**: *string*
+
+
+
+Defined in types/lib/index.d.ts:7
+
+___
+
+### takerAssetAmount
+
+• **takerAssetAmount**: *`BigNumber`*
+
+
+
+Defined in types/lib/index.d.ts:11
___
@@ -1693,52 +1626,34 @@ ___
• **takerAssetData**: *string*
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[takerAssetData](#takerassetdata)*
-*Defined in [asset-swapper/src/types.ts:213](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L213)*
+
+Defined in types/lib/index.d.ts:17
___
-### takerAssetFillAmount
+### takerFee
-• **takerAssetFillAmount**: *`BigNumber`*
+• **takerFee**: *`BigNumber`*
-*Inherited from [MarketSellSwapQuote](#interface-marketsellswapquote).[takerAssetFillAmount](#takerassetfillamount)*
-*Defined in [asset-swapper/src/types.ts:226](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L226)*
+
+Defined in types/lib/index.d.ts:13
___
-### type
+### takerFeeAssetData
-• **type**: *`Sell`*
+• **takerFeeAssetData**: *string*
-*Inherited from [MarketSellSwapQuote](#interface-marketsellswapquote).[type](#type)*
-*Defined in [asset-swapper/src/types.ts:227](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L227)*
-___
-
-### worstCaseQuoteInfo
-
-• **worstCaseQuoteInfo**: *[SwapQuoteInfo](#class-swapquoteinfo)*
-
-*Inherited from [SwapQuoteBase](#interface-swapquotebase).[worstCaseQuoteInfo](#worstcasequoteinfo)*
-
-*Defined in [asset-swapper/src/types.ts:218](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L218)*
+Defined in types/lib/index.d.ts:19
-
-
-
-
-
-
-
-
# Interface: SmartContractParamsInfo <**T**>
Represents the metadata to call a smart contract with parameters.
@@ -1754,11 +1669,11 @@ methodAbi: The ABI of the smart contract method to call with params.
## Properties
-### `Optional` ethAmount
+### ethAmount
-• **ethAmount**? : *`BigNumber`*
+• **ethAmount**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:53](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L53)*
+*Defined in [asset-swapper/src/types.ts:71](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L71)*
___
@@ -1766,7 +1681,7 @@ ___
• **methodAbi**: *`MethodAbi`*
-*Defined in [asset-swapper/src/types.ts:54](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L54)*
+*Defined in [asset-swapper/src/types.ts:72](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L72)*
___
@@ -1774,7 +1689,7 @@ ___
• **params**: *`T`*
-*Defined in [asset-swapper/src/types.ts:51](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L51)*
+*Defined in [asset-swapper/src/types.ts:69](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L69)*
___
@@ -1782,7 +1697,7 @@ ___
• **toAddress**: *string*
-*Defined in [asset-swapper/src/types.ts:52](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L52)*
+*Defined in [asset-swapper/src/types.ts:70](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L70)*
@@ -1809,16 +1724,16 @@ executeSwapQuoteOrThrowAsync: Executes a web3 transaction to swap for tokens wit
### executeSwapQuoteOrThrowAsync
-▸ **executeSwapQuoteOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
+▸ **executeSwapQuoteOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
-*Defined in [asset-swapper/src/types.ts:145](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L145)*
+*Defined in [asset-swapper/src/types.ts:159](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L159)*
**Parameters:**
Name | Type |
------ | ------ |
`quote` | [SwapQuote](#swapquote) |
-`opts` | `Partial` |
+`opts` | `Partial` |
**Returns:** *`Promise`*
@@ -1826,16 +1741,16 @@ ___
### getCalldataOrThrowAsync
-▸ **getCalldataOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
+▸ **getCalldataOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise`*
-*Defined in [asset-swapper/src/types.ts:140](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L140)*
+*Defined in [asset-swapper/src/types.ts:154](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L154)*
**Parameters:**
Name | Type |
------ | ------ |
`quote` | [SwapQuote](#swapquote) |
-`opts` | `Partial` |
+`opts` | `Partial` |
**Returns:** *`Promise`*
@@ -1843,16 +1758,16 @@ ___
### getSmartContractParamsOrThrowAsync
-▸ **getSmartContractParamsOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise>`*
+▸ **getSmartContractParamsOrThrowAsync**(`quote`: [SwapQuote](#swapquote), `opts`: `Partial`): *`Promise>`*
-*Defined in [asset-swapper/src/types.ts:141](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L141)*
+*Defined in [asset-swapper/src/types.ts:155](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L155)*
**Parameters:**
Name | Type |
------ | ------ |
`quote` | [SwapQuote](#swapquote) |
-`opts` | `Partial` |
+`opts` | `Partial` |
**Returns:** *`Promise>`*
@@ -1869,13 +1784,29 @@ chainId: The chainId that the desired orders should be for.
• **chainId**: *number*
-*Defined in [asset-swapper/src/types.ts:152](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L152)*
+*Defined in [asset-swapper/src/types.ts:166](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L166)*
+
+
+
+# Interface: SwapQuoteConsumingOpts
+
+
+## Properties
+
+### useExtensionContract
+
+• **useExtensionContract**: *[ExtensionContractType](#enumeration-extensioncontracttype)*
+
+*Defined in [asset-swapper/src/types.ts:202](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L202)*
# Interface: SwapQuoteExecutionOpts
-Represents the options for executing a swap quote with SwapQuoteConsumer
+takerAddress: The address to perform the buy. Defaults to the first available address from the provider.
+gasLimit: The amount of gas to send with a transaction (in Gwei). Defaults to an eth_estimateGas rpc call.
+gasPrice: Gas price in Wei to use for a transaction
+ethAmount: The amount of eth sent with the execution of a swap
## Properties
@@ -1884,35 +1815,7 @@ Represents the options for executing a swap quote with SwapQuoteConsumer
• **ethAmount**? : *`BigNumber`*
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[ethAmount](#optional-ethamount)*
-
-*Overrides [ForwarderSwapQuoteGetOutputOpts](_asset_swapper_src_types_.forwarderswapquotegetoutputopts.md).[ethAmount](#optional-ethamount)*
-
-*Defined in [asset-swapper/src/types.ts:179](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L179)*
-
-___
-
-### feePercentage
-
-• **feePercentage**: *number*
-
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[feePercentage](#feepercentage)*
-
-*Overrides [ForwarderSwapQuoteGetOutputOpts](_asset_swapper_src_types_.forwarderswapquotegetoutputopts.md).[feePercentage](#feepercentage)*
-
-*Defined in [asset-swapper/src/types.ts:177](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L177)*
-
-___
-
-### feeRecipient
-
-• **feeRecipient**: *string*
-
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[feeRecipient](#feerecipient)*
-
-*Overrides [ForwarderSwapQuoteGetOutputOpts](_asset_swapper_src_types_.forwarderswapquotegetoutputopts.md).[feeRecipient](#feerecipient)*
-
-*Defined in [asset-swapper/src/types.ts:178](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L178)*
+*Defined in [asset-swapper/src/types.ts:184](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L184)*
___
@@ -1920,9 +1823,7 @@ ___
• **gasLimit**? : *undefined | number*
-*Inherited from [SwapQuoteExecutionOptsBase](#interface-swapquoteexecutionoptsbase).[gasLimit](#optional-gaslimit)*
-
-*Defined in [asset-swapper/src/types.ts:167](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L167)*
+*Defined in [asset-swapper/src/types.ts:182](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L182)*
___
@@ -1930,9 +1831,7 @@ ___
• **gasPrice**? : *`BigNumber`*
-*Inherited from [SwapQuoteExecutionOptsBase](#interface-swapquoteexecutionoptsbase).[gasPrice](#optional-gasprice)*
-
-*Defined in [asset-swapper/src/types.ts:168](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L168)*
+*Defined in [asset-swapper/src/types.ts:183](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L183)*
___
@@ -1940,103 +1839,12 @@ ___
• **takerAddress**? : *undefined | string*
-*Inherited from [SwapQuoteExecutionOptsBase](#interface-swapquoteexecutionoptsbase).[takerAddress](#optional-takeraddress)*
-
-*Defined in [asset-swapper/src/types.ts:166](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L166)*
-
-___
-
-### useExtensionContract
-
-• **useExtensionContract**: *[ExtensionContractType](#enumeration-extensioncontracttype)*
-
-*Inherited from [SwapQuoteGetOutputOpts](#interface-swapquotegetoutputopts).[useExtensionContract](#useextensioncontract)*
-
-*Defined in [asset-swapper/src/types.ts:194](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L194)*
-
-
-
-# Interface: SwapQuoteExecutionOptsBase
-
-takerAddress: The address to perform the buy. Defaults to the first available address from the provider.
-gasLimit: The amount of gas to send with a transaction (in Gwei). Defaults to an eth_estimateGas rpc call.
-gasPrice: Gas price in Wei to use for a transaction
-
-
-## Properties
-
-### `Optional` gasLimit
-
-• **gasLimit**? : *undefined | number*
-
-*Defined in [asset-swapper/src/types.ts:167](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L167)*
-
-___
-
-### `Optional` gasPrice
-
-• **gasPrice**? : *`BigNumber`*
-
-*Defined in [asset-swapper/src/types.ts:168](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L168)*
-
-___
-
-### `Optional` takerAddress
-
-• **takerAddress**? : *undefined | string*
-
-*Defined in [asset-swapper/src/types.ts:166](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L166)*
+*Defined in [asset-swapper/src/types.ts:181](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L181)*
# Interface: SwapQuoteGetOutputOpts
-takerAddress: The address to perform the buy. Defaults to the first available address from the provider.
-useConsumerType: If provided, defaults the SwapQuoteConsumer to create output consumed by ConsumerType.
-
-
-## Properties
-
-### `Optional` ethAmount
-
-• **ethAmount**? : *`BigNumber`*
-
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[ethAmount](#optional-ethamount)*
-
-*Defined in [asset-swapper/src/types.ts:179](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L179)*
-
-___
-
-### feePercentage
-
-• **feePercentage**: *number*
-
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[feePercentage](#feepercentage)*
-
-*Defined in [asset-swapper/src/types.ts:177](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L177)*
-
-___
-
-### feeRecipient
-
-• **feeRecipient**: *string*
-
-*Inherited from [ForwarderSwapQuoteGetOutputOpts](#interface-forwarderswapquotegetoutputopts).[feeRecipient](#feerecipient)*
-
-*Defined in [asset-swapper/src/types.ts:178](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L178)*
-
-___
-
-### useExtensionContract
-
-• **useExtensionContract**: *[ExtensionContractType](#enumeration-extensioncontracttype)*
-
-*Defined in [asset-swapper/src/types.ts:194](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L194)*
-
-
-
-# Interface: SwapQuoteGetOutputOptsBase
-
Represents the options provided to a generic SwapQuoteConsumer
@@ -2047,51 +1855,59 @@ Represents the options provided to a generic SwapQuoteConsumer
## Properties
-### feeTakerTokenAmount
+### feeTakerAssetAmount
-• **feeTakerTokenAmount**: *`BigNumber`*
+• **feeTakerAssetAmount**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:256](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L256)*
+*Defined in [asset-swapper/src/types.ts:253](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L253)*
___
-### makerTokenAmount
+### makerAssetAmount
-• **makerTokenAmount**: *`BigNumber`*
+• **makerAssetAmount**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:259](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L259)*
+*Defined in [asset-swapper/src/types.ts:256](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L256)*
___
-### takerTokenAmount
+### protocolFeeInEthAmount
-• **takerTokenAmount**: *`BigNumber`*
+• **protocolFeeInEthAmount**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:258](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L258)*
+*Defined in [asset-swapper/src/types.ts:257](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L257)*
___
-### totalTakerTokenAmount
+### takerAssetAmount
-• **totalTakerTokenAmount**: *`BigNumber`*
+• **takerAssetAmount**: *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:257](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L257)*
+*Defined in [asset-swapper/src/types.ts:254](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L254)*
+
+___
+
+### totalTakerAssetAmount
+
+• **totalTakerAssetAmount**: *`BigNumber`*
+
+*Defined in [asset-swapper/src/types.ts:255](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L255)*
# Interface: SwapQuoteRequestOpts
-shouldDisableRequestingFeeOrders: If set to true, requesting a swapQuote will not perform any computation or requests for fees.
slippagePercentage: The percentage buffer to add to account for slippage. Affects max ETH price estimates. Defaults to 0.2 (20%).
+gasPrice: gas price to determine protocolFee amount, default to ethGasStation fast amount
## Properties
-### shouldDisableRequestingFeeOrders
+### `Optional` gasPrice
-• **shouldDisableRequestingFeeOrders**: *boolean*
+• **gasPrice**? : *`BigNumber`*
-*Defined in [asset-swapper/src/types.ts:267](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L267)*
+*Defined in [asset-swapper/src/types.ts:266](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L266)*
___
@@ -2099,7 +1915,7 @@ ___
• **slippagePercentage**: *number*
-*Defined in [asset-swapper/src/types.ts:268](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L268)*
+*Defined in [asset-swapper/src/types.ts:265](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L265)*
@@ -2116,7 +1932,7 @@ expiryBufferMs: The number of seconds to add when calculating whether an order i
• **chainId**: *number*
-*Defined in [asset-swapper/src/types.ts:277](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L277)*
+*Defined in [asset-swapper/src/types.ts:275](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L275)*
___
@@ -2124,7 +1940,9 @@ ___
• **expiryBufferMs**: *number*
-*Defined in [asset-swapper/src/types.ts:279](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L279)*
+*Overrides [OrderPrunerOpts](_asset_swapper_src_types_.orderpruneropts.md).[expiryBufferMs](#expirybufferms)*
+
+*Defined in [asset-swapper/src/types.ts:277](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L277)*
___
@@ -2132,7 +1950,17 @@ ___
• **orderRefreshIntervalMs**: *number*
-*Defined in [asset-swapper/src/types.ts:278](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L278)*
+*Defined in [asset-swapper/src/types.ts:276](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L276)*
+
+___
+
+### permittedOrderFeeTypes
+
+• **permittedOrderFeeTypes**: *`Set`*
+
+*Inherited from [OrderPrunerOpts](#interface-orderpruneropts).[permittedOrderFeeTypes](#permittedorderfeetypes)*
+
+*Defined in [asset-swapper/src/types.ts:11](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L11)*
@@ -2161,8 +1989,6 @@ ___
-
-
@@ -2175,15 +2001,7 @@ ___
• **components**? : *[DataItem](#class-dataitem)[]*
-*Defined in [ethereum-types/src/index.ts:138](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L138)*
-
-___
-
-### `Optional` internalType
-
-• **internalType**? : *undefined | string*
-
-*Defined in [ethereum-types/src/index.ts:137](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L137)*
+*Defined in [ethereum-types/src/index.ts:137](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L137)*
___
@@ -2191,7 +2009,7 @@ ___
• **name**: *string*
-*Defined in [ethereum-types/src/index.ts:135](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L135)*
+*Defined in [ethereum-types/src/index.ts:135](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L135)*
___
@@ -2199,7 +2017,7 @@ ___
• **type**: *string*
-*Defined in [ethereum-types/src/index.ts:136](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L136)*
+*Defined in [ethereum-types/src/index.ts:136](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L136)*
@@ -2218,7 +2036,7 @@ ___
• **isEIP1193**: *boolean*
-*Defined in [ethereum-types/src/index.ts:73](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L73)*
+*Defined in [ethereum-types/src/index.ts:73](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L73)*
## Methods
@@ -2226,7 +2044,7 @@ ___
▸ **on**(`event`: [EIP1193Event](#eip1193event), `listener`: function): *this*
-*Defined in [ethereum-types/src/index.ts:75](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L75)*
+*Defined in [ethereum-types/src/index.ts:75](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L75)*
**Parameters:**
@@ -2250,7 +2068,7 @@ ___
▸ **send**(`method`: string, `params?`: any[]): *`Promise`*
-*Defined in [ethereum-types/src/index.ts:74](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L74)*
+*Defined in [ethereum-types/src/index.ts:74](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L74)*
**Parameters:**
@@ -2284,7 +2102,7 @@ Name | Type |
▸ **sendAsync**(`payload`: [JSONRPCRequestPayload](_ethereum_types_src_index_.jsonrpcrequestpayload.md), `callback`: [JSONRPCErrorCallback](#jsonrpcerrorcallback)): *void*
-*Defined in [ethereum-types/src/index.ts:14](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L14)*
+*Defined in [ethereum-types/src/index.ts:14](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L14)*
**Parameters:**
@@ -2308,7 +2126,7 @@ Name | Type |
• **id**: *number*
-*Defined in [ethereum-types/src/index.ts:331](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L331)*
+*Defined in [ethereum-types/src/index.ts:330](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L330)*
___
@@ -2316,7 +2134,7 @@ ___
• **jsonrpc**: *string*
-*Defined in [ethereum-types/src/index.ts:332](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L332)*
+*Defined in [ethereum-types/src/index.ts:331](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L331)*
___
@@ -2324,7 +2142,7 @@ ___
• **method**: *string*
-*Defined in [ethereum-types/src/index.ts:330](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L330)*
+*Defined in [ethereum-types/src/index.ts:329](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L329)*
___
@@ -2332,7 +2150,7 @@ ___
• **params**: *any[]*
-*Defined in [ethereum-types/src/index.ts:329](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L329)*
+*Defined in [ethereum-types/src/index.ts:328](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L328)*
@@ -2345,7 +2163,7 @@ ___
• **code**: *number*
-*Defined in [ethereum-types/src/index.ts:337](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L337)*
+*Defined in [ethereum-types/src/index.ts:336](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L336)*
___
@@ -2353,7 +2171,7 @@ ___
• **message**: *string*
-*Defined in [ethereum-types/src/index.ts:336](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L336)*
+*Defined in [ethereum-types/src/index.ts:335](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L335)*
@@ -2366,7 +2184,7 @@ ___
• **error**? : *[JSONRPCResponseError](#class-jsonrpcresponseerror)*
-*Defined in [ethereum-types/src/index.ts:344](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L344)*
+*Defined in [ethereum-types/src/index.ts:343](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L343)*
___
@@ -2374,7 +2192,7 @@ ___
• **id**: *number*
-*Defined in [ethereum-types/src/index.ts:342](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L342)*
+*Defined in [ethereum-types/src/index.ts:341](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L341)*
___
@@ -2382,7 +2200,7 @@ ___
• **jsonrpc**: *string*
-*Defined in [ethereum-types/src/index.ts:343](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L343)*
+*Defined in [ethereum-types/src/index.ts:342](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L342)*
___
@@ -2390,7 +2208,7 @@ ___
• **result**: *any*
-*Defined in [ethereum-types/src/index.ts:341](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L341)*
+*Defined in [ethereum-types/src/index.ts:340](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L340)*
@@ -2409,7 +2227,7 @@ ___
• **constant**: *boolean*
-*Defined in [ethereum-types/src/index.ts:94](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L94)*
+*Defined in [ethereum-types/src/index.ts:94](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L94)*
___
@@ -2417,7 +2235,7 @@ ___
• **inputs**: *[DataItem](#class-dataitem)[]*
-*Defined in [ethereum-types/src/index.ts:92](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L92)*
+*Defined in [ethereum-types/src/index.ts:92](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L92)*
___
@@ -2425,7 +2243,7 @@ ___
• **name**: *string*
-*Defined in [ethereum-types/src/index.ts:91](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L91)*
+*Defined in [ethereum-types/src/index.ts:91](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L91)*
___
@@ -2433,7 +2251,7 @@ ___
• **outputs**: *[DataItem](#class-dataitem)[]*
-*Defined in [ethereum-types/src/index.ts:93](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L93)*
+*Defined in [ethereum-types/src/index.ts:93](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L93)*
___
@@ -2441,7 +2259,7 @@ ___
• **payable**: *boolean*
-*Defined in [ethereum-types/src/index.ts:96](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L96)*
+*Defined in [ethereum-types/src/index.ts:96](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L96)*
___
@@ -2449,7 +2267,7 @@ ___
• **stateMutability**: *[StateMutability](#statemutability)*
-*Defined in [ethereum-types/src/index.ts:95](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L95)*
+*Defined in [ethereum-types/src/index.ts:95](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L95)*
___
@@ -2457,7 +2275,7 @@ ___
• **type**: *string*
-*Defined in [ethereum-types/src/index.ts:90](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L90)*
+*Defined in [ethereum-types/src/index.ts:90](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L90)*
@@ -2486,6 +2304,45 @@ ___
+
+
+
+
+
+# Interface: TupleDataItem
+
+
+## Properties
+
+### components
+
+• **components**: *[DataItem](#class-dataitem)[]*
+
+*Overrides [DataItem](_ethereum_types_src_index_.dataitem.md).[components](#optional-components)*
+
+*Defined in [ethereum-types/src/index.ts:141](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L141)*
+
+___
+
+### name
+
+• **name**: *string*
+
+*Inherited from [DataItem](#interface-dataitem).[name](#name)*
+
+*Defined in [ethereum-types/src/index.ts:135](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L135)*
+
+___
+
+### type
+
+• **type**: *string*
+
+*Inherited from [DataItem](#interface-dataitem).[type](#type)*
+
+*Defined in [ethereum-types/src/index.ts:136](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L136)*
+
+
@@ -2502,7 +2359,7 @@ Error class representing insufficient asset liquidity
\+ **new InsufficientAssetLiquidityError**(`amountAvailableToFill`: `BigNumber`): *[InsufficientAssetLiquidityError](#class-insufficientassetliquidityerror)*
-*Defined in [asset-swapper/src/errors.ts:12](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/errors.ts#L12)*
+*Defined in [asset-swapper/src/errors.ts:12](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/errors.ts#L12)*
**Parameters:**
@@ -2518,7 +2375,7 @@ Name | Type | Description |
• **amountAvailableToFill**: *`BigNumber`*
-*Defined in [asset-swapper/src/errors.ts:12](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/errors.ts#L12)*
+*Defined in [asset-swapper/src/errors.ts:12](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/errors.ts#L12)*
The amount availabe to fill (in base units) factoring in slippage.
@@ -2564,52 +2421,6 @@ ___
-
-
-
-
-# Interface: Web3JsV1Provider
-
-Web3.js version 1 provider interface
-This provider interface was implemented in the pre-1.0Beta releases for Web3.js.
-This interface allowed sending synchonous requests, support for which was later dropped.
-
-
-## Methods
-
-### send
-
-▸ **send**(`payload`: [JSONRPCRequestPayload](_ethereum_types_src_index_.jsonrpcrequestpayload.md)): *[JSONRPCResponsePayload](#class-jsonrpcresponsepayload)*
-
-*Defined in [ethereum-types/src/index.ts:45](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L45)*
-
-**Parameters:**
-
-Name | Type |
------- | ------ |
-`payload` | [JSONRPCRequestPayload](#class-jsonrpcrequestpayload) |
-
-**Returns:** *[JSONRPCResponsePayload](#class-jsonrpcresponsepayload)*
-
-___
-
-### sendAsync
-
-▸ **sendAsync**(`payload`: [JSONRPCRequestPayload](_ethereum_types_src_index_.jsonrpcrequestpayload.md), `callback`: [JSONRPCErrorCallback](#jsonrpcerrorcallback)): *void*
-
-*Defined in [ethereum-types/src/index.ts:44](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L44)*
-
-**Parameters:**
-
-Name | Type |
------- | ------ |
-`payload` | [JSONRPCRequestPayload](#class-jsonrpcrequestpayload) |
-`callback` | [JSONRPCErrorCallback](#jsonrpcerrorcallback) |
-
-**Returns:** *void*
-
-
-
# Interface: Web3JsV2Provider
Web3.js version 2 provider interface
@@ -2623,7 +2434,7 @@ before the first attempts to conform to EIP1193
▸ **send**(`payload`: [JSONRPCRequestPayload](_ethereum_types_src_index_.jsonrpcrequestpayload.md), `callback`: [JSONRPCErrorCallback](#jsonrpcerrorcallback)): *void*
-*Defined in [ethereum-types/src/index.ts:54](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L54)*
+*Defined in [ethereum-types/src/index.ts:54](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L54)*
**Parameters:**
@@ -2649,7 +2460,7 @@ however it does not conform entirely.
▸ **send**(`method`: string, `params?`: any[]): *`Promise`*
-*Defined in [ethereum-types/src/index.ts:63](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L63)*
+*Defined in [ethereum-types/src/index.ts:63](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L63)*
**Parameters:**
@@ -2675,7 +2486,7 @@ add here
• **isMetaMask**? : *undefined | false | true*
-*Defined in [ethereum-types/src/index.ts:31](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L31)*
+*Defined in [ethereum-types/src/index.ts:31](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L31)*
___
@@ -2683,7 +2494,7 @@ ___
• **isParity**? : *undefined | false | true*
-*Defined in [ethereum-types/src/index.ts:32](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L32)*
+*Defined in [ethereum-types/src/index.ts:32](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L32)*
___
@@ -2691,7 +2502,7 @@ ___
• **isZeroExProvider**? : *undefined | false | true*
-*Defined in [ethereum-types/src/index.ts:30](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L30)*
+*Defined in [ethereum-types/src/index.ts:30](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L30)*
## Methods
@@ -2699,7 +2510,7 @@ ___
▸ **enable**(): *`Promise`*
-*Defined in [ethereum-types/src/index.ts:34](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L34)*
+*Defined in [ethereum-types/src/index.ts:34](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L34)*
**Returns:** *`Promise`*
@@ -2709,7 +2520,7 @@ ___
▸ **sendAsync**(`payload`: [JSONRPCRequestPayload](_ethereum_types_src_index_.jsonrpcrequestpayload.md), `callback`: [JSONRPCErrorCallback](#jsonrpcerrorcallback)): *void*
-*Defined in [ethereum-types/src/index.ts:35](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L35)*
+*Defined in [ethereum-types/src/index.ts:35](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L35)*
**Parameters:**
@@ -2726,7 +2537,7 @@ ___
▸ **stop**(): *void*
-*Defined in [ethereum-types/src/index.ts:33](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L33)*
+*Defined in [ethereum-types/src/index.ts:33](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L33)*
**Returns:** *void*
@@ -2741,7 +2552,7 @@ ___
• **accepted**: *`SignedOrder`[]*
-*Defined in [orderbook/src/types.ts:15](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L15)*
+*Defined in [orderbook/src/types.ts:15](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L15)*
___
@@ -2749,7 +2560,7 @@ ___
• **rejected**: *[RejectedOrder](#class-rejectedorder)[]*
-*Defined in [orderbook/src/types.ts:16](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L16)*
+*Defined in [orderbook/src/types.ts:16](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L16)*
@@ -2762,7 +2573,7 @@ ___
• **added**: *`APIOrder`[]*
-*Defined in [orderbook/src/types.ts:6](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L6)*
+*Defined in [orderbook/src/types.ts:6](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L6)*
___
@@ -2770,7 +2581,7 @@ ___
• **assetPairKey**: *string*
-*Defined in [orderbook/src/types.ts:5](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L5)*
+*Defined in [orderbook/src/types.ts:5](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L5)*
___
@@ -2778,7 +2589,7 @@ ___
• **removed**: *`APIOrder`[]*
-*Defined in [orderbook/src/types.ts:7](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L7)*
+*Defined in [orderbook/src/types.ts:7](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L7)*
@@ -2793,7 +2604,7 @@ Constructor options for a Mesh Order Provider
• **websocketEndpoint**: *string*
-*Defined in [orderbook/src/types.ts:50](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L50)*
+*Defined in [orderbook/src/types.ts:52](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L52)*
___
@@ -2801,7 +2612,7 @@ ___
• **wsOpts**? : *`WSOpts`*
-*Defined in [orderbook/src/types.ts:52](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L52)*
+*Defined in [orderbook/src/types.ts:54](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L54)*
@@ -2814,7 +2625,7 @@ ___
• **message**: *string*
-*Defined in [orderbook/src/types.ts:11](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L11)*
+*Defined in [orderbook/src/types.ts:11](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L11)*
___
@@ -2822,7 +2633,7 @@ ___
• **order**: *`SignedOrder`*
-*Defined in [orderbook/src/types.ts:12](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L12)*
+*Defined in [orderbook/src/types.ts:12](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L12)*
@@ -2837,7 +2648,7 @@ Constructor options for a SRA Polling Order Provider
• **chainId**? : *undefined | number*
-*Defined in [orderbook/src/types.ts:42](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L42)*
+*Defined in [orderbook/src/types.ts:44](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L44)*
___
@@ -2845,7 +2656,7 @@ ___
• **httpEndpoint**: *string*
-*Defined in [orderbook/src/types.ts:36](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L36)*
+*Defined in [orderbook/src/types.ts:38](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L38)*
___
@@ -2853,7 +2664,7 @@ ___
• **perPage**? : *undefined | number*
-*Defined in [orderbook/src/types.ts:40](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L40)*
+*Defined in [orderbook/src/types.ts:42](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L42)*
___
@@ -2861,7 +2672,7 @@ ___
• **pollingIntervalMs**: *number*
-*Defined in [orderbook/src/types.ts:38](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L38)*
+*Defined in [orderbook/src/types.ts:40](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L40)*
@@ -2872,11 +2683,19 @@ Constructor options for a SRA Websocket Order Provider
## Properties
+### `Optional` chainId
+
+• **chainId**? : *undefined | number*
+
+*Defined in [orderbook/src/types.ts:30](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L30)*
+
+___
+
### httpEndpoint
• **httpEndpoint**: *string*
-*Defined in [orderbook/src/types.ts:26](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L26)*
+*Defined in [orderbook/src/types.ts:26](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L26)*
___
@@ -2884,7 +2703,7 @@ ___
• **websocketEndpoint**: *string*
-*Defined in [orderbook/src/types.ts:28](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/types.ts#L28)*
+*Defined in [orderbook/src/types.ts:28](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/types.ts#L28)*
@@ -2897,7 +2716,7 @@ ___
• **metaData**: *object*
-*Defined in [types/src/index.ts:408](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L408)*
+*Defined in [types/src/index.ts:403](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L403)*
___
@@ -2905,7 +2724,7 @@ ___
• **order**: *[SignedOrder](#class-signedorder)*
-*Defined in [types/src/index.ts:407](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L407)*
+*Defined in [types/src/index.ts:402](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L402)*
@@ -2920,7 +2739,7 @@ ___
• **assetData**: *string*
-*Defined in [types/src/index.ts:424](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L424)*
+*Defined in [types/src/index.ts:419](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L419)*
___
@@ -2928,7 +2747,7 @@ ___
• **maxAmount**: *`BigNumber`*
-*Defined in [types/src/index.ts:426](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L426)*
+*Defined in [types/src/index.ts:421](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L421)*
___
@@ -2936,7 +2755,7 @@ ___
• **minAmount**: *`BigNumber`*
-*Defined in [types/src/index.ts:425](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L425)*
+*Defined in [types/src/index.ts:420](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L420)*
___
@@ -2944,7 +2763,7 @@ ___
• **precision**: *number*
-*Defined in [types/src/index.ts:427](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L427)*
+*Defined in [types/src/index.ts:422](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L422)*
@@ -2957,7 +2776,7 @@ ___
• **assetDataA**: *[Asset](#class-asset)*
-*Defined in [types/src/index.ts:419](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L419)*
+*Defined in [types/src/index.ts:414](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L414)*
___
@@ -2965,7 +2784,7 @@ ___
• **assetDataB**: *[Asset](#class-asset)*
-*Defined in [types/src/index.ts:420](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L420)*
+*Defined in [types/src/index.ts:415](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L415)*
@@ -3011,6 +2830,8 @@ ___
+
+
@@ -3076,7 +2897,7 @@ ___
*Inherited from [Order](#interface-order).[chainId](#chainid)*
-*Defined in [types/src/index.ts:14](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L14)*
+*Defined in [types/src/index.ts:14](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L14)*
___
@@ -3086,7 +2907,7 @@ ___
*Inherited from [Order](#interface-order).[exchangeAddress](#exchangeaddress)*
-*Defined in [types/src/index.ts:15](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L15)*
+*Defined in [types/src/index.ts:15](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L15)*
___
@@ -3096,7 +2917,7 @@ ___
*Inherited from [Order](#interface-order).[expirationTimeSeconds](#expirationtimeseconds)*
-*Defined in [types/src/index.ts:24](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L24)*
+*Defined in [types/src/index.ts:24](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L24)*
___
@@ -3106,7 +2927,7 @@ ___
*Inherited from [Order](#interface-order).[feeRecipientAddress](#feerecipientaddress)*
-*Defined in [types/src/index.ts:18](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L18)*
+*Defined in [types/src/index.ts:18](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L18)*
___
@@ -3116,7 +2937,7 @@ ___
*Inherited from [Order](#interface-order).[makerAddress](#makeraddress)*
-*Defined in [types/src/index.ts:16](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L16)*
+*Defined in [types/src/index.ts:16](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L16)*
___
@@ -3126,7 +2947,7 @@ ___
*Inherited from [Order](#interface-order).[makerAssetAmount](#makerassetamount)*
-*Defined in [types/src/index.ts:20](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L20)*
+*Defined in [types/src/index.ts:20](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L20)*
___
@@ -3136,7 +2957,7 @@ ___
*Inherited from [Order](#interface-order).[makerAssetData](#makerassetdata)*
-*Defined in [types/src/index.ts:26](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L26)*
+*Defined in [types/src/index.ts:26](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L26)*
___
@@ -3146,7 +2967,7 @@ ___
*Inherited from [Order](#interface-order).[makerFee](#makerfee)*
-*Defined in [types/src/index.ts:22](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L22)*
+*Defined in [types/src/index.ts:22](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L22)*
___
@@ -3156,7 +2977,7 @@ ___
*Inherited from [Order](#interface-order).[makerFeeAssetData](#makerfeeassetdata)*
-*Defined in [types/src/index.ts:28](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L28)*
+*Defined in [types/src/index.ts:28](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L28)*
___
@@ -3166,7 +2987,7 @@ ___
*Inherited from [Order](#interface-order).[salt](#salt)*
-*Defined in [types/src/index.ts:25](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L25)*
+*Defined in [types/src/index.ts:25](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L25)*
___
@@ -3176,7 +2997,7 @@ ___
*Inherited from [Order](#interface-order).[senderAddress](#senderaddress)*
-*Defined in [types/src/index.ts:19](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L19)*
+*Defined in [types/src/index.ts:19](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L19)*
___
@@ -3184,7 +3005,7 @@ ___
• **signature**: *string*
-*Defined in [types/src/index.ts:33](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L33)*
+*Defined in [types/src/index.ts:33](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L33)*
___
@@ -3194,7 +3015,7 @@ ___
*Inherited from [Order](#interface-order).[takerAddress](#takeraddress)*
-*Defined in [types/src/index.ts:17](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L17)*
+*Defined in [types/src/index.ts:17](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L17)*
___
@@ -3204,7 +3025,7 @@ ___
*Inherited from [Order](#interface-order).[takerAssetAmount](#takerassetamount)*
-*Defined in [types/src/index.ts:21](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L21)*
+*Defined in [types/src/index.ts:21](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L21)*
___
@@ -3214,7 +3035,7 @@ ___
*Inherited from [Order](#interface-order).[takerAssetData](#takerassetdata)*
-*Defined in [types/src/index.ts:27](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L27)*
+*Defined in [types/src/index.ts:27](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L27)*
___
@@ -3224,7 +3045,7 @@ ___
*Inherited from [Order](#interface-order).[takerFee](#takerfee)*
-*Defined in [types/src/index.ts:23](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L23)*
+*Defined in [types/src/index.ts:23](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L23)*
___
@@ -3234,7 +3055,7 @@ ___
*Inherited from [Order](#interface-order).[takerFeeAssetData](#takerfeeassetdata)*
-*Defined in [types/src/index.ts:29](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/types/src/index.ts#L29)*
+*Defined in [types/src/index.ts:29](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/types/src/index.ts#L29)*
@@ -3338,13 +3159,85 @@ ___
Ƭ **SwapQuote**: *[MarketBuySwapQuote](#interface-marketbuyswapquote) | [MarketSellSwapQuote](#interface-marketsellswapquote)*
-*Defined in [asset-swapper/src/types.ts:182](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/asset-swapper/src/types.ts#L182)*
+*Defined in [asset-swapper/src/types.ts:205](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/types.ts#L205)*
-___
+
+## Object literals
+
+### `Const` affiliateFeeUtils
+
+#### ▪ **affiliateFeeUtils**: *object*
+
+*Defined in [asset-swapper/src/utils/affiliate_fee_utils.ts:7](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/utils/affiliate_fee_utils.ts#L7)*
+
+#### getTotalEthAmountWithAffiliateFee
+
+▸ **getTotalEthAmountWithAffiliateFee**(`swapQuoteInfo`: [SwapQuoteInfo](#interface-swapquoteinfo), `feePercentage`: number): *`BigNumber`*
+
+*Defined in [asset-swapper/src/utils/affiliate_fee_utils.ts:13](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/utils/affiliate_fee_utils.ts#L13)*
+
+Get the amount of eth to send for a forwarder contract call (includes takerAssetAmount, protocol fees, and specified affiliate fee amount)
+
+**Parameters:**
+
+Name | Type | Description |
+------ | ------ | ------ |
+`swapQuoteInfo` | [SwapQuoteInfo](#interface-swapquoteinfo) | SwapQuoteInfo to generate total eth amount from |
+`feePercentage` | number | Percentage of additive fees to apply to totalTakerAssetAmount + protocol fee. (max 5%) |
+
+**Returns:** *`BigNumber`*
+
+
+
+
+
+
+## Object literals
+
+#### `Const` protocolFeeUtils
+
+#### ▪ **protocolFeeUtils**: *object*
+
+*Defined in [asset-swapper/src/utils/protocol_fee_utils.ts:9](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/utils/protocol_fee_utils.ts#L9)*
+
+#### calculateWorstCaseProtocolFee
+
+▸ **calculateWorstCaseProtocolFee**<**T**>(`orders`: `T`[], `gasPrice`: `BigNumber`): *`BigNumber`*
+
+*Defined in [asset-swapper/src/utils/protocol_fee_utils.ts:27](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/utils/protocol_fee_utils.ts#L27)*
+
+Calculates protocol fee with protofol fee multiplier for each fill.
+
+**Type parameters:**
+
+▪ **T**: *`Order`*
+
+**Parameters:**
+
+Name | Type |
+------ | ------ |
+`orders` | `T`[] |
+`gasPrice` | `BigNumber` |
+
+**Returns:** *`BigNumber`*
+
+#### getGasPriceEstimationOrThrowAsync
+
+▸ **getGasPriceEstimationOrThrowAsync**(): *`Promise`*
+
+*Defined in [asset-swapper/src/utils/protocol_fee_utils.ts:13](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/asset-swapper/src/utils/protocol_fee_utils.ts#L13)*
+
+Gets 'fast' gas price from Eth Gas Station.
+
+**Returns:** *`Promise`*
+
+
+
+
## Type aliases
@@ -3357,7 +3250,7 @@ ___
Ƭ **ConstructorStateMutability**: *"nonpayable" | "payable"*
-*Defined in [ethereum-types/src/index.ts:84](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L84)*
+*Defined in [ethereum-types/src/index.ts:84](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L84)*
___
@@ -3371,7 +3264,7 @@ ___
Ƭ **EIP1193Event**: *"accountsChanged" | "networkChanged" | "close" | "connect" | "notification"*
-*Defined in [ethereum-types/src/index.ts:70](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L70)*
+*Defined in [ethereum-types/src/index.ts:70](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L70)*
Interface for providers that conform to EIP 1193
Source: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md
@@ -3388,7 +3281,7 @@ ___
Ƭ **JSONRPCErrorCallback**: *function*
-*Defined in [ethereum-types/src/index.ts:3](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L3)*
+*Defined in [ethereum-types/src/index.ts:3](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L3)*
#### Type declaration:
@@ -3415,7 +3308,7 @@ ___
Ƭ **StateMutability**: *"pure" | "view" | [ConstructorStateMutability](#constructorstatemutability)*
-*Defined in [ethereum-types/src/index.ts:85](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L85)*
+*Defined in [ethereum-types/src/index.ts:85](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L85)*
___
@@ -3423,7 +3316,7 @@ ___
Ƭ **SupportedProvider**: *[Web3JsProvider](_ethereum_types_src_index_.md#web3jsprovider) | [GanacheProvider](#interface-ganacheprovider) | [EIP1193Provider](#interface-eip1193provider) | [ZeroExProvider](#interface-zeroexprovider)*
-*Defined in [ethereum-types/src/index.ts:9](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L9)*
+*Defined in [ethereum-types/src/index.ts:9](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L9)*
Do not create your own provider. Use an existing provider from a Web3 or ProviderEngine library
Read more about Providers in the guides section of the 0x docs.
@@ -3438,7 +3331,7 @@ ___
Ƭ **Web3JsProvider**: *[Web3JsV1Provider](#interface-web3jsv1provider) | [Web3JsV2Provider](#interface-web3jsv2provider) | [Web3JsV3Provider](#interface-web3jsv3provider)*
-*Defined in [ethereum-types/src/index.ts:11](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/ethereum-types/src/index.ts#L11)*
+*Defined in [ethereum-types/src/index.ts:11](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/ethereum-types/src/index.ts#L11)*
@@ -3451,7 +3344,7 @@ ___
• **DEFAULT_TOKEN_PRECISION**: *`18`* = 18
-*Defined in [orderbook/src/order_provider/base_order_provider.ts:9](https://github.com/0xProject/0x-monorepo/blob/34538f2ce/packages/orderbook/src/order_provider/base_order_provider.ts#L9)*
+*Defined in [orderbook/src/order_provider/base_order_provider.ts:9](https://github.com/0xProject/0x-monorepo/blob/36d7afd2a/packages/orderbook/src/order_provider/base_order_provider.ts#L9)*
diff --git a/packages/asset-swapper/package-lock.json b/packages/asset-swapper/package-lock.json
new file mode 100644
index 0000000000..5bfd95859e
--- /dev/null
+++ b/packages/asset-swapper/package-lock.json
@@ -0,0 +1,1839 @@
+{
+ "name": "@0x/asset-swapper",
+ "version": "2.1.0-beta.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "dev": true
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+ "dev": true
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "dev": true
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "detect-file": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+ "dev": true
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "dev": true,
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "expand-tilde": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
+ "dev": true,
+ "requires": {
+ "homedir-polyfill": "^1.0.1"
+ }
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "findup-sync": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
+ "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
+ "dev": true,
+ "requires": {
+ "detect-file": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "micromatch": "^3.0.4",
+ "resolve-dir": "^1.0.1"
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true
+ },
+ "global-modules": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+ "dev": true,
+ "requires": {
+ "global-prefix": "^3.0.0"
+ },
+ "dependencies": {
+ "global-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+ "dev": true,
+ "requires": {
+ "ini": "^1.3.5",
+ "kind-of": "^6.0.2",
+ "which": "^1.3.1"
+ }
+ }
+ }
+ },
+ "global-prefix": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
+ "dev": true,
+ "requires": {
+ "expand-tilde": "^2.0.2",
+ "homedir-polyfill": "^1.0.1",
+ "ini": "^1.3.4",
+ "is-windows": "^1.0.1",
+ "which": "^1.2.14"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "homedir-polyfill": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
+ "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
+ "dev": true,
+ "requires": {
+ "parse-passwd": "^1.0.0"
+ }
+ },
+ "import-local": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+ "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "^3.0.0",
+ "resolve-cwd": "^2.0.0"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
+ "interpret": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
+ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
+ "dev": true
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "dev": true
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
+ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "dev": true,
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "dev": true,
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dev": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+ "dev": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "parse-passwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
+ "dev": true
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0"
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+ "dev": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "resolve-dir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
+ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
+ "dev": true,
+ "requires": {
+ "expand-tilde": "^2.0.0",
+ "global-modules": "^1.0.0"
+ },
+ "dependencies": {
+ "global-modules": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
+ "dev": true,
+ "requires": {
+ "global-prefix": "^1.0.1",
+ "is-windows": "^1.0.1",
+ "resolve-dir": "^1.0.0"
+ }
+ }
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.1",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "tapable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "v8-compile-cache": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
+ "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==",
+ "dev": true
+ },
+ "webpack-cli": {
+ "version": "3.3.9",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.9.tgz",
+ "integrity": "sha512-xwnSxWl8nZtBl/AFJCOn9pG7s5CYUYdZxmmukv+fAHLcBIHM36dImfpQg3WfShZXeArkWlf6QRw24Klcsv8a5A==",
+ "dev": true,
+ "requires": {
+ "chalk": "2.4.2",
+ "cross-spawn": "6.0.5",
+ "enhanced-resolve": "4.1.0",
+ "findup-sync": "3.0.0",
+ "global-modules": "2.0.0",
+ "import-local": "2.0.0",
+ "interpret": "1.2.0",
+ "loader-utils": "1.2.3",
+ "supports-color": "6.1.0",
+ "v8-compile-cache": "2.0.3",
+ "yargs": "13.2.4"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "13.2.4",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz",
+ "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "os-locale": "^3.1.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
+ "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+}
diff --git a/packages/asset-swapper/package.json b/packages/asset-swapper/package.json
index 20b5a55c8b..17d67da85d 100644
--- a/packages/asset-swapper/package.json
+++ b/packages/asset-swapper/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/asset-swapper",
- "version": "2.1.0-beta.2",
+ "version": "2.1.0-beta.1",
"engines": {
"node": ">=6.12"
},
@@ -40,28 +40,30 @@
},
"homepage": "https://0x.org/asset-swapper",
"dependencies": {
- "@0x/assert": "^2.2.0-beta.2",
- "@0x/connect": "^5.1.0-beta.2",
- "@0x/contract-addresses": "^3.3.0-beta.3",
- "@0x/contract-wrappers": "^12.2.0-beta.2",
- "@0x/dev-utils": "^2.4.0-beta.2",
- "@0x/json-schemas": "^4.1.0-beta.2",
- "@0x/migrations": "^4.4.0-beta.2",
- "@0x/order-utils": "^8.5.0-beta.2",
- "@0x/orderbook": "^0.1.0-beta.2",
- "@0x/subproviders": "^5.1.0-beta.2",
- "@0x/types": "^2.5.0-beta.2",
- "@0x/typescript-typings": "^4.4.0-beta.2",
- "@0x/utils": "^4.6.0-beta.2",
- "@0x/web3-wrapper": "^6.1.0-beta.2",
- "ethereum-types": "^2.2.0-beta.2",
+ "@0x/assert": "^2.2.0-beta.1",
+ "@0x/contracts-dev-utils": "^0.1.0-beta.1",
+ "@0x/contracts-erc20": "^2.3.0-beta.1",
+ "@0x/contracts-exchange": "^2.2.0-beta.1",
+ "@0x/contracts-exchange-forwarder": "^3.1.0-beta.1",
+ "@0x/json-schemas": "^4.1.0-beta.1",
+ "@0x/order-utils": "^8.5.0-beta.1",
+ "@0x/orderbook": "^0.1.0-beta.1",
+ "@0x/types": "^2.5.0-beta.1",
+ "@0x/utils": "^4.6.0-beta.1",
+ "@0x/web3-wrapper": "^6.1.0-beta.1",
+ "ethereum-types": "^2.2.0-beta.1",
"lodash": "^4.17.11"
},
"devDependencies": {
+ "@0x/contract-addresses": "^3.3.0-beta.2",
"@0x/contracts-test-utils": "^3.2.0-beta.2",
+ "@0x/dev-utils": "^2.4.0-beta.1",
"@0x/mesh-rpc-client": "^7.0.4-beta-0xv3",
+ "@0x/migrations": "^4.4.0-beta.1",
+ "@0x/subproviders": "^5.1.0-beta.1",
"@0x/ts-doc-gen": "^0.0.22",
- "@0x/tslint-config": "^3.1.0-beta.2",
+ "@0x/tslint-config": "^3.1.0-beta.1",
+ "@0x/typescript-typings": "^4.4.0-beta.1",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
diff --git a/packages/asset-swapper/src/constants.ts b/packages/asset-swapper/src/constants.ts
index 97a7eba606..fa7f1cf366 100644
--- a/packages/asset-swapper/src/constants.ts
+++ b/packages/asset-swapper/src/constants.ts
@@ -1,55 +1,68 @@
-import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import {
- ForwarderSwapQuoteExecutionOpts,
- ForwarderSwapQuoteGetOutputOpts,
- OrdersAndFillableAmounts,
+ ForwarderExtensionContractOpts,
+ OrderPrunerOpts,
+ OrderPrunerPermittedFeeTypes,
+ SwapQuoteExecutionOpts,
+ SwapQuoteGetOutputOpts,
SwapQuoteRequestOpts,
SwapQuoterOpts,
} from './types';
+const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info';
const NULL_BYTES = '0x';
+const NULL_ERC20_ASSET_DATA = '0xf47261b00000000000000000000000000000000000000000000000000000000000000000';
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
const MAINNET_CHAIN_ID = 1;
const ONE_SECOND_MS = 1000;
const DEFAULT_PER_PAGE = 1000;
+const PROTOCOL_FEE_MULTIPLIER = 150000;
-const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = {
- chainId: MAINNET_CHAIN_ID,
- orderRefreshIntervalMs: 10000, // 10 seconds
+const DEFAULT_ORDER_PRUNER_OPTS: OrderPrunerOpts = {
expiryBufferMs: 120000, // 2 minutes
+ permittedOrderFeeTypes: new Set([
+ OrderPrunerPermittedFeeTypes.NoFees,
+ OrderPrunerPermittedFeeTypes.MakerDenominatedTakerFee,
+ ]), // Default asset-swapper for CFL oriented fee types
};
-const DEFAULT_FORWARDER_SWAP_QUOTE_GET_OPTS: ForwarderSwapQuoteGetOutputOpts = {
+const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = {
+ ...{
+ chainId: MAINNET_CHAIN_ID,
+ orderRefreshIntervalMs: 10000, // 10 seconds
+ },
+ ...DEFAULT_ORDER_PRUNER_OPTS,
+};
+
+const DEFAULT_FORWARDER_SWAP_QUOTE_GET_OPTS: SwapQuoteGetOutputOpts & ForwarderExtensionContractOpts = {
feePercentage: 0,
feeRecipient: NULL_ADDRESS,
};
-const DEFAULT_FORWARDER_SWAP_QUOTE_EXECUTE_OPTS: ForwarderSwapQuoteExecutionOpts = DEFAULT_FORWARDER_SWAP_QUOTE_GET_OPTS;
+const DEFAULT_FORWARDER_SWAP_QUOTE_EXECUTE_OPTS: SwapQuoteExecutionOpts &
+ ForwarderExtensionContractOpts = DEFAULT_FORWARDER_SWAP_QUOTE_GET_OPTS;
const DEFAULT_SWAP_QUOTE_REQUEST_OPTS: SwapQuoteRequestOpts = {
- shouldDisableRequestingFeeOrders: false,
slippagePercentage: 0.2, // 20% slippage protection,
};
-const EMPTY_ORDERS_AND_FILLABLE_AMOUNTS: OrdersAndFillableAmounts = {
- orders: [] as SignedOrder[],
- remainingFillableMakerAssetAmounts: [] as BigNumber[],
-};
-
export const constants = {
+ ETH_GAS_STATION_API_BASE_URL,
NULL_BYTES,
ZERO_AMOUNT: new BigNumber(0),
NULL_ADDRESS,
MAINNET_CHAIN_ID,
+ DEFAULT_ORDER_PRUNER_OPTS,
ETHER_TOKEN_DECIMALS: 18,
ONE_AMOUNT: new BigNumber(1),
+ MAX_AFFILIATE_FEE_PERCENTAGE: 0.05,
ONE_SECOND_MS,
DEFAULT_SWAP_QUOTER_OPTS,
DEFAULT_FORWARDER_SWAP_QUOTE_GET_OPTS,
DEFAULT_FORWARDER_SWAP_QUOTE_EXECUTE_OPTS,
DEFAULT_SWAP_QUOTE_REQUEST_OPTS,
- EMPTY_ORDERS_AND_FILLABLE_AMOUNTS,
DEFAULT_PER_PAGE,
+ PROTOCOL_FEE_MULTIPLIER,
+ NULL_ERC20_ASSET_DATA,
};
diff --git a/packages/asset-swapper/src/index.ts b/packages/asset-swapper/src/index.ts
index fa5973fd22..fbd1e31f34 100644
--- a/packages/asset-swapper/src/index.ts
+++ b/packages/asset-swapper/src/index.ts
@@ -20,11 +20,13 @@ export {
ConstructorStateMutability,
} from 'ethereum-types';
-export { SignedOrder, AssetPairsItem, APIOrder, Asset } from '@0x/types';
+export { SignedOrder, AssetPairsItem, APIOrder, Asset, Order } from '@0x/types';
export { BigNumber } from '@0x/utils';
export { SwapQuoteConsumer } from './quote_consumers/swap_quote_consumer';
export { SwapQuoter } from './swap_quoter';
+export { protocolFeeUtils } from './utils/protocol_fee_utils';
+export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
export { InsufficientAssetLiquidityError } from './errors';
export {
@@ -34,21 +36,16 @@ export {
SwapQuoteConsumerOpts,
CalldataInfo,
ExtensionContractType,
+ SwapQuoteConsumingOpts,
+ LiquidityForTakerMakerAssetDataPair,
SwapQuoteGetOutputOpts,
+ PrunedSignedOrder,
SwapQuoteExecutionOpts,
SwapQuoteInfo,
GetExtensionContractTypeOpts,
- SwapQuoteExecutionOptsBase,
- SwapQuoteGetOutputOptsBase,
- ForwarderSwapQuoteExecutionOpts,
- ForwarderSwapQuoteGetOutputOpts,
SmartContractParamsInfo,
MarketBuySwapQuote,
MarketSellSwapQuote,
- MarketBuySwapQuoteWithAffiliateFee,
- MarketSellSwapQuoteWithAffiliateFee,
- LiquidityForAssetData,
- OrdersAndFillableAmounts,
SwapQuoteConsumerBase,
SwapQuoteRequestOpts,
} from './types';
diff --git a/packages/asset-swapper/src/quote_consumers/exchange_swap_quote_consumer.ts b/packages/asset-swapper/src/quote_consumers/exchange_swap_quote_consumer.ts
index 996a652c10..e8e796c5cd 100644
--- a/packages/asset-swapper/src/quote_consumers/exchange_swap_quote_consumer.ts
+++ b/packages/asset-swapper/src/quote_consumers/exchange_swap_quote_consumer.ts
@@ -1,5 +1,5 @@
-import { ContractError, ContractWrappers, ForwarderError } from '@0x/contract-wrappers';
-import { MarketOperation } from '@0x/types';
+import { ContractAddresses } from '@0x/contract-addresses';
+import { ExchangeContract } from '@0x/contracts-exchange';
import { AbiEncoder, providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from '@0x/web3-wrapper';
import { MethodAbi } from 'ethereum-types';
@@ -9,13 +9,13 @@ import { constants } from '../constants';
import {
CalldataInfo,
ExchangeSmartContractParams,
+ MarketOperation,
SmartContractParamsInfo,
SwapQuote,
SwapQuoteConsumerBase,
- SwapQuoteConsumerError,
SwapQuoteConsumerOpts,
- SwapQuoteExecutionOptsBase,
- SwapQuoteGetOutputOptsBase,
+ SwapQuoteExecutionOpts,
+ SwapQuoteGetOutputOpts,
} from '../types';
import { assert } from '../utils/assert';
import { swapQuoteConsumerUtils } from '../utils/swap_quote_consumer_utils';
@@ -25,23 +25,24 @@ export class ExchangeSwapQuoteConsumer implements SwapQuoteConsumerBase = {}) {
+ constructor(
+ supportedProvider: SupportedProvider,
+ contractAddresses: ContractAddresses,
+ options: Partial = {},
+ ) {
const { chainId } = _.merge({}, constants.DEFAULT_SWAP_QUOTER_OPTS, options);
assert.isNumber('chainId', chainId);
-
const provider = providerUtils.standardizeOrThrow(supportedProvider);
this.provider = provider;
this.chainId = chainId;
- this._contractWrappers = new ContractWrappers(this.provider, {
- chainId,
- });
+ this._exchangeContract = new ExchangeContract(contractAddresses.exchange, supportedProvider);
}
public async getCalldataOrThrowAsync(
quote: SwapQuote,
- opts: Partial,
+ opts: Partial,
): Promise {
assert.isValidSwapQuote('quote', quote);
@@ -69,7 +70,7 @@ export class ExchangeSwapQuoteConsumer implements SwapQuoteConsumerBase,
+ _opts: Partial = {},
): Promise> {
assert.isValidSwapQuote('quote', quote);
@@ -77,8 +78,6 @@ export class ExchangeSwapQuoteConsumer implements SwapQuoteConsumerBase o.signature);
- const optimizedOrders = swapQuoteConsumerUtils.optimizeOrdersForMarketExchangeOperation(orders, quote.type);
-
let params: ExchangeSmartContractParams;
let methodName: string;
@@ -86,45 +85,43 @@ export class ExchangeSwapQuoteConsumer implements SwapQuoteConsumerBase,
+ opts: Partial,
): Promise {
assert.isValidSwapQuote('quote', quote);
- const { takerAddress, gasLimit, gasPrice } = opts;
+ const { takerAddress, gasLimit, gasPrice, ethAmount } = opts;
if (takerAddress !== undefined) {
assert.isETHAddressHex('takerAddress', takerAddress);
@@ -135,41 +132,38 @@ export class ExchangeSwapQuoteConsumer implements SwapQuoteConsumerBase o.signature))
- .sendTransactionAsync({
- from: finalTakerAddress,
- gas: gasLimit,
- gasPrice,
- });
- } else {
- const { takerAssetFillAmount } = quote;
- txHash = await this._contractWrappers.exchange
- .marketSellOrdersNoThrow(orders, takerAssetFillAmount, orders.map(o => o.signature))
- .sendTransactionAsync({
- from: finalTakerAddress,
- gas: gasLimit,
- gasPrice,
- });
- }
- return txHash;
- } catch (err) {
- if (_.includes(err.message, ContractError.SignatureRequestDenied)) {
- throw new Error(SwapQuoteConsumerError.SignatureRequestDenied);
- } else if (_.includes(err.message, ForwarderError.CompleteFillFailed)) {
- throw new Error(SwapQuoteConsumerError.TransactionValueTooLow);
- } else {
- throw err;
- }
+ const value = ethAmount || quote.worstCaseQuoteInfo.protocolFeeInEthAmount;
+ let txHash: string;
+ if (quote.type === MarketOperation.Buy) {
+ const { makerAssetFillAmount } = quote;
+ txHash = await this._exchangeContract
+ .marketBuyOrdersFillOrKill(orders, makerAssetFillAmount, orders.map(o => o.signature))
+ .sendTransactionAsync({
+ from: finalTakerAddress,
+ gas: gasLimit,
+ gasPrice,
+ value,
+ });
+ } else {
+ const { takerAssetFillAmount } = quote;
+ txHash = await this._exchangeContract
+ .marketSellOrdersFillOrKill(orders, takerAssetFillAmount, orders.map(o => o.signature))
+ .sendTransactionAsync({
+ from: finalTakerAddress,
+ gas: gasLimit,
+ gasPrice,
+ value,
+ });
}
+ // TODO(dorothy-zbornak): Handle signature request denied
+ // (see contract-wrappers/decorators)
+ // and ExchangeRevertErrors.IncompleteFillError.
+ return txHash;
}
}
diff --git a/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts b/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts
index 82420df4a9..6d38db113e 100644
--- a/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts
+++ b/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts
@@ -1,5 +1,6 @@
-import { ContractError, ContractWrappers, ForwarderError } from '@0x/contract-wrappers';
-import { MarketOperation } from '@0x/types';
+import { ContractAddresses } from '@0x/contract-addresses';
+import { DevUtilsContract } from '@0x/contracts-dev-utils';
+import { ForwarderContract } from '@0x/contracts-exchange-forwarder';
import { AbiEncoder, providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from '@0x/web3-wrapper';
import { MethodAbi } from 'ethereum-types';
@@ -8,14 +9,15 @@ import * as _ from 'lodash';
import { constants } from '../constants';
import {
CalldataInfo,
+ ForwarderExtensionContractOpts,
ForwarderSmartContractParams,
- ForwarderSwapQuoteExecutionOpts,
- ForwarderSwapQuoteGetOutputOpts,
+ MarketOperation,
SmartContractParamsInfo,
SwapQuote,
SwapQuoteConsumerBase,
- SwapQuoteConsumerError,
SwapQuoteConsumerOpts,
+ SwapQuoteExecutionOpts,
+ SwapQuoteGetOutputOpts,
} from '../types';
import { affiliateFeeUtils } from '../utils/affiliate_fee_utils';
import { assert } from '../utils/assert';
@@ -26,18 +28,23 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase = {}) {
+ constructor(
+ supportedProvider: SupportedProvider,
+ contractAddresses: ContractAddresses,
+ options: Partial = {},
+ ) {
const { chainId } = _.merge({}, constants.DEFAULT_SWAP_QUOTER_OPTS, options);
assert.isNumber('chainId', chainId);
-
const provider = providerUtils.standardizeOrThrow(supportedProvider);
this.provider = provider;
this.chainId = chainId;
- this._contractWrappers = new ContractWrappers(this.provider, {
- chainId,
- });
+ this._contractAddresses = contractAddresses;
+ this._forwarder = new ForwarderContract(contractAddresses.forwarder, supportedProvider);
+ this._devUtils = new DevUtilsContract(contractAddresses.devUtils, supportedProvider);
}
/**
@@ -47,21 +54,21 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase,
+ opts: Partial = {},
): Promise {
assert.isValidForwarderSwapQuote('quote', quote, await this._getEtherTokenAssetDataOrThrowAsync());
const { toAddress, methodAbi, ethAmount, params } = await this.getSmartContractParamsOrThrowAsync(quote, opts);
const abiEncoder = new AbiEncoder.Method(methodAbi);
- const { orders, signatures, feeOrders, feeSignatures, feePercentage, feeRecipient } = params;
+ const { orders, signatures, feePercentage, feeRecipient } = params;
let args: any[];
if (params.type === MarketOperation.Buy) {
const { makerAssetFillAmount } = params;
- args = [orders, makerAssetFillAmount, signatures, feeOrders, feeSignatures, feePercentage, feeRecipient];
+ args = [orders, makerAssetFillAmount, signatures, feePercentage, feeRecipient];
} else {
- args = [orders, signatures, feeOrders, feeSignatures, feePercentage, feeRecipient];
+ args = [orders, signatures, feePercentage, feeRecipient];
}
const calldataHexString = abiEncoder.encode(args, { shouldOptimize: true });
return {
@@ -79,47 +86,42 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase,
+ opts: Partial = {},
): Promise> {
assert.isValidForwarderSwapQuote('quote', quote, await this._getEtherTokenAssetDataOrThrowAsync());
- const { ethAmount, feeRecipient, feePercentage: unFormattedFeePercentage } = _.merge(
+ const { ethAmount: providedEthAmount, feeRecipient, feePercentage } = _.merge(
{},
constants.DEFAULT_FORWARDER_SWAP_QUOTE_GET_OPTS,
opts,
);
- assert.isValidPercentage('feePercentage', unFormattedFeePercentage);
+ assert.isValidPercentage('feePercentage', feePercentage);
assert.isETHAddressHex('feeRecipient', feeRecipient);
- if (ethAmount !== undefined) {
- assert.isBigNumber('ethAmount', ethAmount);
+ if (providedEthAmount !== undefined) {
+ assert.isBigNumber('ethAmount', providedEthAmount);
}
- const quoteWithAffiliateFee = affiliateFeeUtils.getSwapQuoteWithAffiliateFee(quote, unFormattedFeePercentage);
-
- const { orders, feeOrders, worstCaseQuoteInfo } = quoteWithAffiliateFee;
+ const { orders, worstCaseQuoteInfo } = quote;
// lowercase input addresses
const normalizedFeeRecipientAddress = feeRecipient.toLowerCase();
const signatures = _.map(orders, o => o.signature);
- const feeSignatures = _.map(feeOrders, o => o.signature);
- const feePercentage = utils.numberPercentageToEtherTokenAmountPercentage(unFormattedFeePercentage);
+ const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage);
let params: ForwarderSmartContractParams;
let methodName: string;
- if (quoteWithAffiliateFee.type === MarketOperation.Buy) {
- const { makerAssetFillAmount } = quoteWithAffiliateFee;
+ if (quote.type === MarketOperation.Buy) {
+ const { makerAssetFillAmount } = quote;
params = {
orders,
makerAssetFillAmount,
signatures,
- feeOrders,
- feeSignatures,
- feePercentage,
+ feePercentage: formattedFeePercentage,
feeRecipient: normalizedFeeRecipientAddress,
type: MarketOperation.Buy,
};
@@ -129,23 +131,21 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase,
+ opts: Partial,
): Promise {
assert.isValidForwarderSwapQuote('quote', quote, await this._getEtherTokenAssetDataOrThrowAsync());
- const { ethAmount, takerAddress, gasLimit, gasPrice, feeRecipient, feePercentage } = _.merge(
+ const { ethAmount: providedEthAmount, takerAddress, gasLimit, gasPrice, feeRecipient, feePercentage } = _.merge(
{},
constants.DEFAULT_FORWARDER_SWAP_QUOTE_EXECUTE_OPTS,
opts,
@@ -169,8 +169,8 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase o.signature),
- formattedFeePercentage,
- feeRecipient,
- )
- .sendTransactionAsync({
- value,
- from: finalTakerAddress.toLowerCase(),
- gas: gasLimit,
- gasPrice,
- });
- } else {
- txHash = await this._contractWrappers.forwarder
- .marketSellOrdersWithEth(orders, orders.map(o => o.signature), formattedFeePercentage, feeRecipient)
- .sendTransactionAsync({
- value,
- from: finalTakerAddress.toLowerCase(),
- gas: gasLimit,
- gasPrice,
- });
- }
- return txHash;
- } catch (err) {
- if (_.includes(err.message, ContractError.SignatureRequestDenied)) {
- throw new Error(SwapQuoteConsumerError.SignatureRequestDenied);
- } else if (_.includes(err.message, ForwarderError.CompleteFillFailed)) {
- throw new Error(SwapQuoteConsumerError.TransactionValueTooLow);
- } else {
- throw err;
- }
+ let txHash: string;
+ if (quote.type === MarketOperation.Buy) {
+ const { makerAssetFillAmount } = quote;
+ txHash = await this._forwarder
+ .marketBuyOrdersWithEth(
+ orders,
+ makerAssetFillAmount,
+ orders.map(o => o.signature),
+ formattedFeePercentage,
+ feeRecipient,
+ )
+ .sendTransactionAsync({
+ from: finalTakerAddress,
+ gas: gasLimit,
+ gasPrice,
+ value: providedEthAmount || ethAmountWithFees,
+ });
+ } else {
+ txHash = await this._forwarder
+ .marketSellOrdersWithEth(orders, orders.map(o => o.signature), formattedFeePercentage, feeRecipient)
+ .sendTransactionAsync({
+ from: finalTakerAddress,
+ gas: gasLimit,
+ gasPrice,
+ value: providedEthAmount || ethAmountWithFees,
+ });
}
+ // TODO(dorothy-zbornak): Handle signature request denied
+ // (see contract-wrappers/decorators)
+ // and ForwarderRevertErrors.CompleteBuyFailed.
+ return txHash;
}
private async _getEtherTokenAssetDataOrThrowAsync(): Promise {
- return this._contractWrappers.devUtils
- .encodeERC20AssetData(this._contractWrappers.contractAddresses.etherToken)
- .callAsync();
+ return this._devUtils.encodeERC20AssetData(this._contractAddresses.etherToken).callAsync();
}
}
diff --git a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts b/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts
index a07b587e52..c184b768f4 100644
--- a/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts
+++ b/packages/asset-swapper/src/quote_consumers/swap_quote_consumer.ts
@@ -1,4 +1,4 @@
-import { ContractWrappers } from '@0x/contract-wrappers';
+import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from '@0x/web3-wrapper';
import * as _ from 'lodash';
@@ -13,6 +13,7 @@ import {
SwapQuote,
SwapQuoteConsumerBase,
SwapQuoteConsumerOpts,
+ SwapQuoteConsumingOpts,
SwapQuoteExecutionOpts,
SwapQuoteGetOutputOpts,
} from '../types';
@@ -28,7 +29,14 @@ export class SwapQuoteConsumer implements SwapQuoteConsumerBase = {},
+ ): SwapQuoteConsumer {
+ return new SwapQuoteConsumer(supportedProvider, options);
+ }
constructor(supportedProvider: SupportedProvider, options: Partial = {}) {
const { chainId } = _.merge({}, constants.DEFAULT_SWAP_QUOTER_OPTS, options);
@@ -37,22 +45,19 @@ export class SwapQuoteConsumer implements SwapQuoteConsumerBase = {},
+ opts: Partial = {},
): Promise {
assert.isValidSwapQuote('quote', quote);
const consumer = await this._getConsumerForSwapQuoteAsync(opts);
@@ -60,13 +65,13 @@ export class SwapQuoteConsumer implements SwapQuoteConsumerBase = {},
+ opts: Partial = {},
): Promise> {
assert.isValidSwapQuote('quote', quote);
const consumer = await this._getConsumerForSwapQuoteAsync(opts);
@@ -74,33 +79,38 @@ export class SwapQuoteConsumer implements SwapQuoteConsumerBase = {},
+ opts: Partial = {},
): Promise {
assert.isValidSwapQuote('quote', quote);
const consumer = await this._getConsumerForSwapQuoteAsync(opts);
return consumer.executeSwapQuoteOrThrowAsync(quote, opts);
}
+ /**
+ * Given a SwapQuote, returns optimal 0x protocol interface (extension or no extension) to perform the swap.
+ * @param quote An object that conforms to SwapQuote. See type definition for more information.
+ * @param opts Options for getting optimal exteion contract to fill quote. See type definition for more information.
+ */
public async getOptimalExtensionContractTypeAsync(
quote: SwapQuote,
opts: Partial = {},
): Promise {
return swapQuoteConsumerUtils.getExtensionContractTypeForSwapQuoteAsync(
quote,
- this._contractWrappers,
+ this._contractAddresses,
this.provider,
opts,
);
}
private async _getConsumerForSwapQuoteAsync(
- opts: Partial,
+ opts: Partial,
): Promise> {
if (opts.useExtensionContract === ExtensionContractType.Forwarder) {
return this._forwarderConsumer;
diff --git a/packages/asset-swapper/src/swap_quoter.ts b/packages/asset-swapper/src/swap_quoter.ts
index 5d2d39bd8c..b0f3df7d81 100644
--- a/packages/asset-swapper/src/swap_quoter.ts
+++ b/packages/asset-swapper/src/swap_quoter.ts
@@ -1,18 +1,20 @@
-import { ContractWrappers } from '@0x/contract-wrappers';
+import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
+import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { schemas } from '@0x/json-schemas';
-import { assetDataUtils, SignedOrder } from '@0x/order-utils';
+import { SignedOrder } from '@0x/order-utils';
import { MeshOrderProviderOpts, Orderbook, SRAPollingOrderProviderOpts } from '@0x/orderbook';
-import { MarketOperation } from '@0x/types';
import { BigNumber, providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash';
import { constants } from './constants';
import {
- LiquidityForAssetData,
+ LiquidityForTakerMakerAssetDataPair,
MarketBuySwapQuote,
+ MarketOperation,
MarketSellSwapQuote,
- OrdersAndFillableAmounts,
+ OrderPrunerPermittedFeeTypes,
+ PrunedSignedOrder,
SwapQuote,
SwapQuoteRequestOpts,
SwapQuoterError,
@@ -20,16 +22,19 @@ import {
} from './types';
import { assert } from './utils/assert';
import { calculateLiquidity } from './utils/calculate_liquidity';
-import { orderProviderResponseProcessor } from './utils/order_provider_response_processor';
+import { OrderPruner } from './utils/order_prune_utils';
+import { protocolFeeUtils } from './utils/protocol_fee_utils';
+import { sortingUtils } from './utils/sorting_utils';
import { swapQuoteCalculator } from './utils/swap_quote_calculator';
-import { utils } from './utils/utils';
export class SwapQuoter {
public readonly provider: ZeroExProvider;
public readonly orderbook: Orderbook;
public readonly expiryBufferMs: number;
- private readonly _contractWrappers: ContractWrappers;
-
+ public readonly permittedOrderFeeTypes: Set;
+ private readonly _contractAddresses: ContractAddresses;
+ private readonly _orderPruner: OrderPruner;
+ private readonly _devUtilsContract: DevUtilsContract;
/**
* Instantiates a new SwapQuoter instance given existing liquidity in the form of orders and feeOrders.
* @param supportedProvider The Provider instance you would like to use for interacting with the Ethereum network.
@@ -132,7 +137,11 @@ export class SwapQuoter {
* @return An instance of SwapQuoter
*/
constructor(supportedProvider: SupportedProvider, orderbook: Orderbook, options: Partial = {}) {
- const { chainId, expiryBufferMs } = _.merge({}, constants.DEFAULT_SWAP_QUOTER_OPTS, options);
+ const { chainId, expiryBufferMs, permittedOrderFeeTypes } = _.merge(
+ {},
+ constants.DEFAULT_SWAP_QUOTER_OPTS,
+ options,
+ );
const provider = providerUtils.standardizeOrThrow(supportedProvider);
assert.isValidOrderbook('orderbook', orderbook);
assert.isNumber('chainId', chainId);
@@ -140,10 +149,15 @@ export class SwapQuoter {
this.provider = provider;
this.orderbook = orderbook;
this.expiryBufferMs = expiryBufferMs;
- this._contractWrappers = new ContractWrappers(this.provider, {
- chainId,
+ this.permittedOrderFeeTypes = permittedOrderFeeTypes;
+ this._contractAddresses = getContractAddressesForChainOrThrow(chainId);
+ this._devUtilsContract = new DevUtilsContract(this._contractAddresses.devUtils, provider);
+ this._orderPruner = new OrderPruner(this._devUtilsContract, {
+ expiryBufferMs: this.expiryBufferMs,
+ permittedOrderFeeTypes: this.permittedOrderFeeTypes,
});
}
+
/**
* Get a `SwapQuote` containing all information relevant to fulfilling a swap between a desired ERC20 token address and ERC20 owned by a provided address.
* You can then pass the `SwapQuote` to a `SwapQuoteConsumer` to execute a buy, or process SwapQuote for on-chain consumption.
@@ -214,12 +228,8 @@ export class SwapQuoter {
assert.isETHAddressHex('makerTokenAddress', makerTokenAddress);
assert.isETHAddressHex('takerTokenAddress', takerTokenAddress);
assert.isBigNumber('makerAssetBuyAmount', makerAssetBuyAmount);
- const makerAssetData = await this._contractWrappers.devUtils
- .encodeERC20AssetData(makerTokenAddress)
- .callAsync();
- const takerAssetData = await this._contractWrappers.devUtils
- .encodeERC20AssetData(takerTokenAddress)
- .callAsync();
+ const makerAssetData = await this._devUtilsContract.encodeERC20AssetData(makerTokenAddress).callAsync();
+ const takerAssetData = await this._devUtilsContract.encodeERC20AssetData(takerTokenAddress).callAsync();
const swapQuote = this.getMarketBuySwapQuoteForAssetDataAsync(
makerAssetData,
takerAssetData,
@@ -248,12 +258,8 @@ export class SwapQuoter {
assert.isETHAddressHex('makerTokenAddress', makerTokenAddress);
assert.isETHAddressHex('takerTokenAddress', takerTokenAddress);
assert.isBigNumber('takerAssetSellAmount', takerAssetSellAmount);
- const makerAssetData = await this._contractWrappers.devUtils
- .encodeERC20AssetData(makerTokenAddress)
- .callAsync();
- const takerAssetData = await this._contractWrappers.devUtils
- .encodeERC20AssetData(takerTokenAddress)
- .callAsync();
+ const makerAssetData = await this._devUtilsContract.encodeERC20AssetData(makerTokenAddress).callAsync();
+ const takerAssetData = await this._devUtilsContract.encodeERC20AssetData(takerTokenAddress).callAsync();
const swapQuote = this.getMarketSellSwapQuoteForAssetDataAsync(
makerAssetData,
takerAssetData,
@@ -269,27 +275,26 @@ export class SwapQuoter {
* @param makerAssetData The makerAssetData of the desired asset to swap for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* @param takerAssetData The takerAssetData of the asset to swap makerAssetData for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
*
- * @return An object that conforms to LiquidityForAssetData that satisfies the request. See type definition for more information.
+ * @return An object that conforms to LiquidityForTakerMakerAssetDataPair that satisfies the request. See type definition for more information.
*/
public async getLiquidityForMakerTakerAssetDataPairAsync(
makerAssetData: string,
takerAssetData: string,
- ): Promise {
+ ): Promise {
assert.isString('makerAssetData', makerAssetData);
assert.isString('takerAssetData', takerAssetData);
- assetDataUtils.decodeAssetDataOrThrow(makerAssetData);
- assetDataUtils.decodeAssetDataOrThrow(takerAssetData);
-
+ await this._devUtilsContract.revertIfInvalidAssetData(takerAssetData).callAsync();
+ await this._devUtilsContract.revertIfInvalidAssetData(makerAssetData).callAsync();
const assetPairs = await this.getAvailableMakerAssetDatasAsync(takerAssetData);
if (!assetPairs.includes(makerAssetData)) {
return {
- makerTokensAvailableInBaseUnits: new BigNumber(0),
- takerTokensAvailableInBaseUnits: new BigNumber(0),
+ makerAssetAvailableInBaseUnits: new BigNumber(0),
+ takerAssetAvailableInBaseUnits: new BigNumber(0),
};
}
- const ordersAndFillableAmounts = await this.getOrdersAndFillableAmountsAsync(makerAssetData, takerAssetData);
- return calculateLiquidity(ordersAndFillableAmounts);
+ const prunedOrders = await this.getPrunedSignedOrdersAsync(makerAssetData, takerAssetData);
+ return calculateLiquidity(prunedOrders);
}
/**
@@ -299,7 +304,7 @@ export class SwapQuoter {
*/
public async getAvailableTakerAssetDatasAsync(makerAssetData: string): Promise {
assert.isString('makerAssetData', makerAssetData);
- assetDataUtils.decodeAssetDataOrThrow(makerAssetData);
+ await this._devUtilsContract.revertIfInvalidAssetData(makerAssetData).callAsync();
const allAssetPairs = await this.orderbook.getAvailableAssetDatasAsync();
const assetPairs = allAssetPairs
.filter(pair => pair.assetDataA.assetData === makerAssetData)
@@ -314,7 +319,7 @@ export class SwapQuoter {
*/
public async getAvailableMakerAssetDatasAsync(takerAssetData: string): Promise {
assert.isString('takerAssetData', takerAssetData);
- assetDataUtils.decodeAssetDataOrThrow(takerAssetData);
+ await this._devUtilsContract.revertIfInvalidAssetData(takerAssetData).callAsync();
const allAssetPairs = await this.orderbook.getAvailableAssetDatasAsync();
const assetPairs = allAssetPairs
.filter(pair => pair.assetDataB.assetData === takerAssetData)
@@ -324,6 +329,8 @@ export class SwapQuoter {
/**
* Validates the taker + maker asset pair is available from the order provider provided to `SwapQuote`.
+ * @param makerAssetData The makerAssetData of the desired asset to swap for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
+ * @param takerAssetData The takerAssetData of the asset to swap makerAssetData for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
*
* @return A boolean on if the taker, maker pair exists
*/
@@ -333,41 +340,31 @@ export class SwapQuoter {
): Promise {
assert.isString('makerAssetData', makerAssetData);
assert.isString('takerAssetData', takerAssetData);
- assetDataUtils.decodeAssetDataOrThrow(makerAssetData);
- assetDataUtils.decodeAssetDataOrThrow(takerAssetData);
+ await this._devUtilsContract.revertIfInvalidAssetData(makerAssetData).callAsync();
+ await this._devUtilsContract.revertIfInvalidAssetData(takerAssetData).callAsync();
const availableMakerAssetDatas = await this.getAvailableMakerAssetDatasAsync(takerAssetData);
return _.includes(availableMakerAssetDatas, makerAssetData);
}
/**
- * Grab orders from the map, if there is a miss or it is time to refresh, fetch and process the orders
+ * Grab orders from the order provider, prunes for valid orders with provided OrderPruner options
* @param makerAssetData The makerAssetData of the desired asset to swap for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* @param takerAssetData The takerAssetData of the asset to swap makerAssetData for (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
*/
- public async getOrdersAndFillableAmountsAsync(
+ public async getPrunedSignedOrdersAsync(
makerAssetData: string,
takerAssetData: string,
- ): Promise {
+ ): Promise {
assert.isString('makerAssetData', makerAssetData);
assert.isString('takerAssetData', takerAssetData);
- assetDataUtils.decodeAssetDataOrThrow(makerAssetData);
- assetDataUtils.decodeAssetDataOrThrow(takerAssetData);
- const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
+ await this._devUtilsContract.revertIfInvalidAssetData(takerAssetData).callAsync();
+ await this._devUtilsContract.revertIfInvalidAssetData(makerAssetData).callAsync();
// get orders
- const response = await this.orderbook.getOrdersAsync(makerAssetData, takerAssetData);
- const adaptedResponse = { orders: response.map(o => ({ ...o.order, ...o.metaData })) };
- // since the order provider is an injected dependency, validate that it respects the API
- // ie. it should only return maker/taker assetDatas that are specified
- orderProviderResponseProcessor.throwIfInvalidResponse(adaptedResponse, makerAssetData, takerAssetData);
- // process the responses into one object
- const isMakerAssetZrxToken = makerAssetData === zrxTokenAssetData;
- const ordersAndFillableAmounts = await orderProviderResponseProcessor.processAsync(
- adaptedResponse,
- isMakerAssetZrxToken,
- this.expiryBufferMs,
- this._contractWrappers.orderValidator,
- );
- return ordersAndFillableAmounts;
+ const apiOrders = await this.orderbook.getOrdersAsync(makerAssetData, takerAssetData);
+ const orders = _.map(apiOrders, o => o.order);
+ const prunedOrders = await this._orderPruner.pruneSignedOrdersAsync(orders);
+ const sortedPrunedOrders = sortingUtils.sortOrders(prunedOrders);
+ return sortedPrunedOrders;
}
/**
@@ -375,18 +372,16 @@ export class SwapQuoter {
* @param swapQuote The swapQuote in question to check enough allowance enabled for 0x exchange contracts to conduct the swap.
* @param takerAddress The address of the taker of the provided swapQuote
*/
- public async isTakerAddressAllowanceEnoughForBestAndWorstQuoteInfoAsync(
+ public async isSwapQuoteFillableByTakerAddressAsync(
swapQuote: SwapQuote,
takerAddress: string,
): Promise<[boolean, boolean]> {
- const orderValidator = this._contractWrappers.orderValidator;
- const balanceAndAllowance = await orderValidator
- .getBalanceAndAllowance(takerAddress, swapQuote.takerAssetData)
+ const balanceAndAllowance = await this._devUtilsContract
+ .getBalanceAndAssetProxyAllowance(takerAddress, swapQuote.takerAssetData)
.callAsync();
- const allowance = balanceAndAllowance[1];
return [
- allowance.isGreaterThanOrEqualTo(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount),
- allowance.isGreaterThanOrEqualTo(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount),
+ balanceAndAllowance[1].isGreaterThanOrEqualTo(swapQuote.bestCaseQuoteInfo.totalTakerAssetAmount),
+ balanceAndAllowance[1].isGreaterThanOrEqualTo(swapQuote.worstCaseQuoteInfo.totalTakerAssetAmount),
];
}
@@ -398,13 +393,10 @@ export class SwapQuoter {
}
/**
- * Get the assetData that represents the ZRX token.
- * Will throw if ZRX does not exist for the current chain.
+ * Utility function to get assetData for Ether token.
*/
- private async _getZrxTokenAssetDataOrThrowAsync(): Promise {
- return this._contractWrappers.devUtils
- .encodeERC20AssetData(this._contractWrappers.contractAddresses.zrxToken)
- .callAsync();
+ public async getEtherTokenAssetDataOrThrowAsync(): Promise {
+ return this._devUtilsContract.encodeERC20AssetData(this._contractAddresses.etherToken).callAsync();
}
/**
@@ -417,30 +409,20 @@ export class SwapQuoter {
marketOperation: MarketOperation,
options: Partial,
): Promise {
- const { slippagePercentage, shouldDisableRequestingFeeOrders } = _.merge(
- {},
- constants.DEFAULT_SWAP_QUOTE_REQUEST_OPTS,
- options,
- );
+ const { slippagePercentage } = _.merge({}, constants.DEFAULT_SWAP_QUOTE_REQUEST_OPTS, options);
assert.isString('makerAssetData', makerAssetData);
assert.isString('takerAssetData', takerAssetData);
assert.isNumber('slippagePercentage', slippagePercentage);
- const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
- const isMakerAssetZrxToken = makerAssetData === zrxTokenAssetData;
- // get the relevant orders for the makerAsset
- const ordersAndFillableAmounts = await this.getOrdersAndFillableAmountsAsync(makerAssetData, takerAssetData);
- const doesOrdersRequireFeeOrders =
- !isMakerAssetZrxToken && utils.isFeeOrdersRequiredToFillOrders(ordersAndFillableAmounts);
- const isRequestingFeeOrders = !shouldDisableRequestingFeeOrders && doesOrdersRequireFeeOrders;
- let feeOrdersAndFillableAmounts = constants.EMPTY_ORDERS_AND_FILLABLE_AMOUNTS;
- if (isRequestingFeeOrders) {
- feeOrdersAndFillableAmounts = await this.getOrdersAndFillableAmountsAsync(
- zrxTokenAssetData,
- takerAssetData,
- );
+ let gasPrice: BigNumber;
+ if (!!options.gasPrice) {
+ gasPrice = options.gasPrice;
+ assert.isBigNumber('gasPrice', gasPrice);
+ } else {
+ gasPrice = await protocolFeeUtils.getGasPriceEstimationOrThrowAsync();
}
-
- if (ordersAndFillableAmounts.orders.length === 0) {
+ // get the relevant orders for the makerAsset
+ const prunedOrders = await this.getPrunedSignedOrdersAsync(makerAssetData, takerAssetData);
+ if (prunedOrders.length === 0) {
throw new Error(
`${
SwapQuoterError.AssetUnavailable
@@ -448,33 +430,21 @@ export class SwapQuoter {
);
}
- if (isRequestingFeeOrders && feeOrdersAndFillableAmounts.orders.length === 0) {
- throw new Error(
- `${
- SwapQuoterError.FeeAssetUnavailable
- }: For makerAssetdata ${makerAssetData} and takerAssetdata ${takerAssetData}`,
- );
- }
-
let swapQuote: SwapQuote;
if (marketOperation === MarketOperation.Buy) {
swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- feeOrdersAndFillableAmounts,
+ prunedOrders,
assetFillAmount,
slippagePercentage,
- isMakerAssetZrxToken,
- shouldDisableRequestingFeeOrders,
+ gasPrice,
);
} else {
swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- feeOrdersAndFillableAmounts,
+ prunedOrders,
assetFillAmount,
slippagePercentage,
- isMakerAssetZrxToken,
- shouldDisableRequestingFeeOrders,
+ gasPrice,
);
}
diff --git a/packages/asset-swapper/src/types.ts b/packages/asset-swapper/src/types.ts
index 1015b3d243..771157cf47 100644
--- a/packages/asset-swapper/src/types.ts
+++ b/packages/asset-swapper/src/types.ts
@@ -1,7 +1,27 @@
-import { MarketOperation, SignedOrder } from '@0x/types';
+import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { MethodAbi } from 'ethereum-types';
+/**
+ * expiryBufferMs: The number of seconds to add when calculating whether an order is expired or not. Defaults to 300s (5m).
+ * permittedOrderFeeTypes: A set of all the takerFee types that OrderPruner will filter for
+ */
+export interface OrderPrunerOpts {
+ expiryBufferMs: number;
+ permittedOrderFeeTypes: Set;
+}
+
+/**
+ * Represents the on-chain metadata of a signed order
+ */
+export interface OrderPrunerOnChainMetadata {
+ orderStatus: number;
+ orderHash: string;
+ orderTakerAssetFilledAmount: BigNumber;
+ fillableTakerAssetAmount: BigNumber;
+ isValidSignature: boolean;
+}
+
/**
* makerAssetData: The assetData representing the desired makerAsset.
* takerAssetData: The assetData representing the desired takerAsset.
@@ -12,18 +32,14 @@ export interface OrderProviderRequest {
}
/**
- * orders: An array of orders with optional remaining fillable makerAsset amounts. See type for more info.
+ * fillableMakerAssetAmount: Amount of makerAsset that is fillable
+ * fillableTakerAssetAmount: Amount of takerAsset that is fillable
+ * fillableTakerFeeAmount: Amount of takerFee paid to fill fillableTakerAssetAmount
*/
-export interface OrderProviderResponse {
- orders: SignedOrderWithRemainingFillableMakerAssetAmount[];
-}
-
-/**
- * A normal SignedOrder with one extra optional property `remainingFillableMakerAssetAmount`
- * remainingFillableMakerAssetAmount: The amount of the makerAsset that is available to be filled
- */
-export interface SignedOrderWithRemainingFillableMakerAssetAmount extends SignedOrder {
- remainingFillableMakerAssetAmount?: BigNumber;
+export interface PrunedSignedOrder extends SignedOrder {
+ fillableMakerAssetAmount: BigNumber;
+ fillableTakerAssetAmount: BigNumber;
+ fillableTakerFeeAmount: BigNumber;
}
/**
@@ -31,13 +47,13 @@ export interface SignedOrderWithRemainingFillableMakerAssetAmount extends Signed
* calldataHexString: The hexstring of the calldata.
* methodAbi: The ABI of the smart contract method to call.
* toAddress: The contract address to call.
- * ethAmount: If provided, the eth amount in wei to send with the smart contract call.
+ * ethAmount: The eth amount in wei to send with the smart contract call.
*/
export interface CalldataInfo {
calldataHexString: string;
methodAbi: MethodAbi;
toAddress: string;
- ethAmount?: BigNumber;
+ ethAmount: BigNumber;
}
/**
@@ -50,7 +66,7 @@ export interface CalldataInfo {
export interface SmartContractParamsInfo {
params: T;
toAddress: string;
- ethAmount?: BigNumber;
+ ethAmount: BigNumber;
methodAbi: MethodAbi;
}
@@ -95,14 +111,10 @@ export enum ExtensionContractType {
export type ExchangeSmartContractParams = ExchangeMarketBuySmartContractParams | ExchangeMarketSellSmartContractParams;
/**
- * feeOrders: An array of objects conforming to SignedOrder. These orders can be used to cover the fees for the orders param above.
- * feeSignatures: An array of signatures that attest that the maker of the orders in fact made the orders.
* feePercentage: Optional affiliate fee percentage used to calculate the eth amount paid to fee recipient.
* feeRecipient: The address where affiliate fees are sent. Defaults to null address (0x000...000).
*/
export interface ForwarderSmartContractParamsBase {
- feeOrders: SignedOrder[];
- feeSignatures: string[];
feePercentage: BigNumber;
feeRecipient: string;
}
@@ -137,12 +149,12 @@ export type SmartContractParams = ForwarderSmartContractParams | ExchangeSmartCo
* executeSwapQuoteOrThrowAsync: Executes a web3 transaction to swap for tokens with provided SwapQuote. Throws if invalid SwapQuote is provided.
*/
export interface SwapQuoteConsumerBase {
- getCalldataOrThrowAsync(quote: SwapQuote, opts: Partial): Promise;
+ getCalldataOrThrowAsync(quote: SwapQuote, opts: Partial): Promise;
getSmartContractParamsOrThrowAsync(
quote: SwapQuote,
- opts: Partial,
+ opts: Partial,
): Promise>;
- executeSwapQuoteOrThrowAsync(quote: SwapQuote, opts: Partial): Promise;
+ executeSwapQuoteOrThrowAsync(quote: SwapQuote, opts: Partial): Promise;
}
/**
@@ -155,28 +167,37 @@ export interface SwapQuoteConsumerOpts {
/**
* Represents the options provided to a generic SwapQuoteConsumer
*/
-export interface SwapQuoteGetOutputOptsBase {}
+export interface SwapQuoteGetOutputOpts {}
/**
* takerAddress: The address to perform the buy. Defaults to the first available address from the provider.
* gasLimit: The amount of gas to send with a transaction (in Gwei). Defaults to an eth_estimateGas rpc call.
* gasPrice: Gas price in Wei to use for a transaction
+ * ethAmount: The amount of eth sent with the execution of a swap
*/
-export interface SwapQuoteExecutionOptsBase extends SwapQuoteGetOutputOptsBase {
+export interface SwapQuoteExecutionOpts extends SwapQuoteGetOutputOpts {
takerAddress?: string;
gasLimit?: number;
gasPrice?: BigNumber;
+ ethAmount?: BigNumber;
}
/**
+ * ethAmount: The amount of eth (in Wei) sent to the forwarder contract.
* feePercentage: percentage (up to 5%) of the taker asset paid to feeRecipient
* feeRecipient: address of the receiver of the feePercentage of taker asset
- * ethAmount: The amount of eth (in Wei) sent to the forwarder contract.
*/
-export interface ForwarderSwapQuoteGetOutputOpts extends SwapQuoteGetOutputOptsBase {
+export interface ForwarderExtensionContractOpts {
+ ethAmount?: BigNumber;
feePercentage: number;
feeRecipient: string;
- ethAmount?: BigNumber;
+}
+
+/*
+ * Options for how SwapQuoteConsumer will generate output
+ */
+export interface SwapQuoteConsumingOpts {
+ useExtensionContract: ExtensionContractType;
}
export type SwapQuote = MarketBuySwapQuote | MarketSellSwapQuote;
@@ -186,26 +207,10 @@ export interface GetExtensionContractTypeOpts {
ethAmount?: BigNumber;
}
-/**
- * takerAddress: The address to perform the buy. Defaults to the first available address from the provider.
- * useConsumerType: If provided, defaults the SwapQuoteConsumer to create output consumed by ConsumerType.
- */
-export interface SwapQuoteGetOutputOpts extends ForwarderSwapQuoteGetOutputOpts {
- useExtensionContract: ExtensionContractType;
-}
-
-export interface ForwarderSwapQuoteExecutionOpts extends ForwarderSwapQuoteGetOutputOpts, SwapQuoteExecutionOptsBase {}
-
-/**
- * Represents the options for executing a swap quote with SwapQuoteConsumer
- */
-export interface SwapQuoteExecutionOpts extends SwapQuoteGetOutputOpts, ForwarderSwapQuoteExecutionOpts {}
-
/**
* takerAssetData: String that represents a specific taker asset (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* makerAssetData: String that represents a specific maker asset (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* orders: An array of objects conforming to SignedOrder. These orders can be used to cover the requested assetBuyAmount plus slippage.
- * feeOrders: An array of objects conforming to SignedOrder. These orders can be used to cover the fees for the orders param above.
* bestCaseQuoteInfo: Info about the best case price for the asset.
* worstCaseQuoteInfo: Info about the worst case price for the asset.
*/
@@ -213,7 +218,6 @@ export interface SwapQuoteBase {
takerAssetData: string;
makerAssetData: string;
orders: SignedOrder[];
- feeOrders: SignedOrder[];
bestCaseQuoteInfo: SwapQuoteInfo;
worstCaseQuoteInfo: SwapQuoteInfo;
}
@@ -236,36 +240,28 @@ export interface MarketBuySwapQuote extends SwapQuoteBase {
type: MarketOperation.Buy;
}
-export interface SwapQuoteWithAffiliateFeeBase {
- feePercentage: number;
-}
-
-export interface MarketSellSwapQuoteWithAffiliateFee extends SwapQuoteWithAffiliateFeeBase, MarketSellSwapQuote {}
-
-export interface MarketBuySwapQuoteWithAffiliateFee extends SwapQuoteWithAffiliateFeeBase, MarketBuySwapQuote {}
-
-export type SwapQuoteWithAffiliateFee = MarketBuySwapQuoteWithAffiliateFee | MarketSellSwapQuoteWithAffiliateFee;
-
/**
- * feeTakerTokenAmount: The amount of takerToken required any fee concerned with completing the swap.
- * takerTokenAmount: The amount of takerToken required to conduct the swap.
- * totalTakerTokenAmount: The total amount of takerToken required to complete the swap (filling orders, feeOrders, and paying affiliate fee)
- * makerTokenAmount: The amount of makerToken that will be acquired through the swap.
+ * feeTakerAssetAmount: The amount of takerAsset reserved for paying takerFees when swapping for desired assets.
+ * takerAssetAmount: The amount of takerAsset swapped for desired makerAsset.
+ * totalTakerAssetAmount: The total amount of takerAsset required to complete the swap (filling orders, and paying takerFees).
+ * makerAssetAmount: The amount of makerAsset that will be acquired through the swap.
+ * protocolFeeInEthAmount: The amount of eth to pay as protocol fee to perform the swap for desired asset.
*/
export interface SwapQuoteInfo {
- feeTakerTokenAmount: BigNumber;
- totalTakerTokenAmount: BigNumber;
- takerTokenAmount: BigNumber;
- makerTokenAmount: BigNumber;
+ feeTakerAssetAmount: BigNumber;
+ takerAssetAmount: BigNumber;
+ totalTakerAssetAmount: BigNumber;
+ makerAssetAmount: BigNumber;
+ protocolFeeInEthAmount: BigNumber;
}
/**
- * shouldDisableRequestingFeeOrders: If set to true, requesting a swapQuote will not perform any computation or requests for fees.
* slippagePercentage: The percentage buffer to add to account for slippage. Affects max ETH price estimates. Defaults to 0.2 (20%).
+ * gasPrice: gas price to determine protocolFee amount, default to ethGasStation fast amount
*/
export interface SwapQuoteRequestOpts {
- shouldDisableRequestingFeeOrders: boolean;
slippagePercentage: number;
+ gasPrice?: BigNumber;
}
/**
@@ -273,7 +269,7 @@ export interface SwapQuoteRequestOpts {
* orderRefreshIntervalMs: The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* expiryBufferMs: The number of seconds to add when calculating whether an order is expired or not. Defaults to 300s (5m).
*/
-export interface SwapQuoterOpts {
+export interface SwapQuoterOpts extends OrderPrunerOpts {
chainId: number;
orderRefreshIntervalMs: number;
expiryBufferMs: number;
@@ -295,28 +291,33 @@ export enum SwapQuoteConsumerError {
*/
export enum SwapQuoterError {
NoEtherTokenContractFound = 'NO_ETHER_TOKEN_CONTRACT_FOUND',
- NoZrxTokenContractFound = 'NO_ZRX_TOKEN_CONTRACT_FOUND',
StandardRelayerApiError = 'STANDARD_RELAYER_API_ERROR',
InsufficientAssetLiquidity = 'INSUFFICIENT_ASSET_LIQUIDITY',
- InsufficientZrxLiquidity = 'INSUFFICIENT_ZRX_LIQUIDITY',
- InvalidOrderProviderResponse = 'INVALID_ORDER_PROVIDER_RESPONSE',
AssetUnavailable = 'ASSET_UNAVAILABLE',
- FeeAssetUnavailable = 'FEE_ASSET_UNAVAILABLE',
+ NoGasPriceProvidedOrEstimated = 'NO_GAS_PRICE_PROVIDED_OR_ESTIMATED',
}
/**
- * orders: An array of signed orders
- * remainingFillableMakerAssetAmounts: A list of fillable amounts for the signed orders. The index of an item in the array associates the amount with the corresponding order.
+ * Represents available liquidity for a given assetData.
*/
-export interface OrdersAndFillableAmounts {
- orders: SignedOrder[];
- remainingFillableMakerAssetAmounts: BigNumber[];
+export interface LiquidityForTakerMakerAssetDataPair {
+ makerAssetAvailableInBaseUnits: BigNumber;
+ takerAssetAvailableInBaseUnits: BigNumber;
}
/**
- * Represents available liquidity for a given assetData
+ * Represents two main market operations supported by asset-swapper.
*/
-export interface LiquidityForAssetData {
- makerTokensAvailableInBaseUnits: BigNumber;
- takerTokensAvailableInBaseUnits: BigNumber;
+export enum MarketOperation {
+ Sell = 'Sell',
+ Buy = 'Buy',
+}
+
+/**
+ * Represents varying order takerFee types that can be pruned for by OrderPruner.
+ */
+export enum OrderPrunerPermittedFeeTypes {
+ NoFees = 'NO_FEES',
+ MakerDenominatedTakerFee = 'MAKER_DENOMINATED_TAKER_FEE',
+ TakerDenominatedTakerFee = 'TAKER_DENOMINATED_TAKER_FEE',
}
diff --git a/packages/asset-swapper/src/utils/affiliate_fee_utils.ts b/packages/asset-swapper/src/utils/affiliate_fee_utils.ts
index 7276a8dd92..9d595ac339 100644
--- a/packages/asset-swapper/src/utils/affiliate_fee_utils.ts
+++ b/packages/asset-swapper/src/utils/affiliate_fee_utils.ts
@@ -1,29 +1,24 @@
import { BigNumber } from '@0x/utils';
-import * as _ from 'lodash';
-import { SwapQuote, SwapQuoteInfo, SwapQuoteWithAffiliateFee } from '../types';
+import { constants } from '../constants';
+import { SwapQuoteInfo } from '../types';
+
+import { assert } from './assert';
export const affiliateFeeUtils = {
- getSwapQuoteWithAffiliateFee(quote: SwapQuote, feePercentage: number): SwapQuoteWithAffiliateFee {
- const newQuote = _.clone(quote);
- newQuote.bestCaseQuoteInfo = getSwapQuoteInfoWithAffiliateFee(newQuote.bestCaseQuoteInfo, feePercentage);
- newQuote.worstCaseQuoteInfo = getSwapQuoteInfoWithAffiliateFee(newQuote.worstCaseQuoteInfo, feePercentage);
- return { ...newQuote, ...{ feePercentage } };
+ /**
+ * Get the amount of eth to send for a forwarder contract call (includes takerAssetAmount, protocol fees, and specified affiliate fee amount)
+ * @param swapQuoteInfo SwapQuoteInfo to generate total eth amount from
+ * @param feePercentage Percentage of additive fees to apply to totalTakerAssetAmount + protocol fee. (max 5%)
+ */
+ getTotalEthAmountWithAffiliateFee(swapQuoteInfo: SwapQuoteInfo, feePercentage: number): BigNumber {
+ assert.assert(
+ feePercentage >= 0 && feePercentage <= constants.MAX_AFFILIATE_FEE_PERCENTAGE,
+ 'feePercentage must be between range 0-0.05 (inclusive)',
+ );
+ const ethAmount = swapQuoteInfo.protocolFeeInEthAmount.plus(swapQuoteInfo.totalTakerAssetAmount);
+ const affiliateFeeAmount = ethAmount.multipliedBy(feePercentage);
+ const ethAmountWithFees = ethAmount.plus(affiliateFeeAmount);
+ return ethAmountWithFees;
},
};
-
-/**
- * Adds a fee based on feePercentage of the takerTokenAmount and adds it to the feeTakerTokenAmount and totalTakerTokenAmount
- * @param quoteInfo quote information to add fee to
- * @param feePercentage the percentage of takerTokenAmount charged additionally as a fee
- */
-const getSwapQuoteInfoWithAffiliateFee = (quoteInfo: SwapQuoteInfo, feePercentage: number): SwapQuoteInfo => {
- const newQuoteInfo = _.clone(quoteInfo);
- const affiliateFeeAmount = quoteInfo.takerTokenAmount
- .multipliedBy(feePercentage)
- .integerValue(BigNumber.ROUND_CEIL);
- const newFeeAmount = quoteInfo.feeTakerTokenAmount.plus(affiliateFeeAmount);
- newQuoteInfo.feeTakerTokenAmount = newFeeAmount;
- newQuoteInfo.totalTakerTokenAmount = newFeeAmount.plus(quoteInfo.takerTokenAmount);
- return newQuoteInfo;
-};
diff --git a/packages/asset-swapper/src/utils/assert.ts b/packages/asset-swapper/src/utils/assert.ts
index 1840d13913..99e2626cb0 100644
--- a/packages/asset-swapper/src/utils/assert.ts
+++ b/packages/asset-swapper/src/utils/assert.ts
@@ -1,10 +1,12 @@
import { assert as sharedAssert } from '@0x/assert';
import { schemas } from '@0x/json-schemas';
import { Orderbook } from '@0x/orderbook';
-import { MarketOperation, SignedOrder } from '@0x/types';
+import { Order, SignedOrder } from '@0x/types';
import * as _ from 'lodash';
-import { OrderProviderRequest, SwapQuote, SwapQuoteInfo } from '../types';
+import { MarketOperation, OrderProviderRequest, SwapQuote, SwapQuoteInfo } from '../types';
+
+import { utils } from './utils';
export const assert = {
...sharedAssert,
@@ -12,8 +14,7 @@ export const assert = {
sharedAssert.isHexString(`${variableName}.takerAssetData`, swapQuote.takerAssetData);
sharedAssert.isHexString(`${variableName}.makerAssetData`, swapQuote.makerAssetData);
sharedAssert.doesConformToSchema(`${variableName}.orders`, swapQuote.orders, schemas.signedOrdersSchema);
- sharedAssert.doesConformToSchema(`${variableName}.feeOrders`, swapQuote.feeOrders, schemas.signedOrdersSchema);
- assert.isValidOrdersForSwapQuote(
+ assert.isValidSwapQuoteOrders(
`${variableName}.orders`,
swapQuote.orders,
swapQuote.makerAssetData,
@@ -27,7 +28,7 @@ export const assert = {
sharedAssert.isBigNumber(`${variableName}.takerAssetFillAmount`, swapQuote.takerAssetFillAmount);
}
},
- isValidOrdersForSwapQuote(
+ isValidSwapQuoteOrders(
variableName: string,
orders: SignedOrder[],
makerAssetData: string,
@@ -48,10 +49,21 @@ export const assert = {
);
});
},
+ isValidOrdersForSwapQuoter(variableName: string, orders: T[]): void {
+ _.every(orders, (order: T, index: number) => {
+ assert.assert(
+ order.takerFee.isZero() ||
+ utils.isOrderTakerFeePayableWithTakerAsset(order) ||
+ utils.isOrderTakerFeePayableWithMakerAsset(order),
+ `Expected ${variableName}[${index}].takerFeeAssetData to be ${order.makerAssetData} or ${
+ order.takerAssetData
+ } but found ${order.takerFeeAssetData}`,
+ );
+ });
+ },
isValidForwarderSwapQuote(variableName: string, swapQuote: SwapQuote, wethAssetData: string): void {
assert.isValidSwapQuote(variableName, swapQuote);
assert.isValidForwarderSignedOrders(`${variableName}.orders`, swapQuote.orders, wethAssetData);
- assert.isValidForwarderSignedOrders(`${variableName}.feeOrders`, swapQuote.feeOrders, wethAssetData);
},
isValidForwarderSignedOrders(variableName: string, orders: SignedOrder[], wethAssetData: string): void {
_.forEach(orders, (o: SignedOrder, i: number) => {
@@ -65,10 +77,10 @@ export const assert = {
);
},
isValidSwapQuoteInfo(variableName: string, swapQuoteInfo: SwapQuoteInfo): void {
- sharedAssert.isBigNumber(`${variableName}.feeTakerTokenAmount`, swapQuoteInfo.feeTakerTokenAmount);
- sharedAssert.isBigNumber(`${variableName}.totalTakerTokenAmount`, swapQuoteInfo.totalTakerTokenAmount);
- sharedAssert.isBigNumber(`${variableName}.takerTokenAmount`, swapQuoteInfo.takerTokenAmount);
- sharedAssert.isBigNumber(`${variableName}.takerTokenAmount`, swapQuoteInfo.makerTokenAmount);
+ sharedAssert.isBigNumber(`${variableName}.feeTakerAssetAmount`, swapQuoteInfo.feeTakerAssetAmount);
+ sharedAssert.isBigNumber(`${variableName}.totalTakerAssetAmount`, swapQuoteInfo.totalTakerAssetAmount);
+ sharedAssert.isBigNumber(`${variableName}.takerAssetAmount`, swapQuoteInfo.takerAssetAmount);
+ sharedAssert.isBigNumber(`${variableName}.makerAssetAmount`, swapQuoteInfo.makerAssetAmount);
},
isValidOrderbook(variableName: string, orderFetcher: Orderbook): void {
sharedAssert.isFunction(`${variableName}.getOrdersAsync`, orderFetcher.getOrdersAsync);
diff --git a/packages/asset-swapper/src/utils/calculate_liquidity.ts b/packages/asset-swapper/src/utils/calculate_liquidity.ts
index 45a881961d..4cf1711cf0 100644
--- a/packages/asset-swapper/src/utils/calculate_liquidity.ts
+++ b/packages/asset-swapper/src/utils/calculate_liquidity.ts
@@ -1,40 +1,27 @@
-import { orderCalculationUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
-import { LiquidityForAssetData, OrdersAndFillableAmounts } from '../types';
+import { LiquidityForTakerMakerAssetDataPair, PrunedSignedOrder } from '../types';
-export const calculateLiquidity = (ordersAndFillableAmounts: OrdersAndFillableAmounts): LiquidityForAssetData => {
- const { orders, remainingFillableMakerAssetAmounts } = ordersAndFillableAmounts;
- const liquidityInBigNumbers = orders.reduce(
- (acc, order, curIndex) => {
- const availableMakerAssetAmount = remainingFillableMakerAssetAmounts[curIndex];
- if (availableMakerAssetAmount === undefined) {
- throw new Error(`No corresponding fillableMakerAssetAmounts at index ${curIndex}`);
- }
+import { utils } from './utils';
- const makerTokensAvailableForCurrentOrder = availableMakerAssetAmount;
- const takerTokensAvailableForCurrentOrder = orderCalculationUtils.getTakerFillAmount(
- order,
- makerTokensAvailableForCurrentOrder,
- );
+export const calculateLiquidity = (prunedOrders: PrunedSignedOrder[]): LiquidityForTakerMakerAssetDataPair => {
+ const liquidityInBigNumbers = prunedOrders.reduce(
+ (acc, order) => {
+ const fillableMakerAssetAmount = utils.isOrderTakerFeePayableWithMakerAsset(order)
+ ? order.fillableMakerAssetAmount.minus(order.fillableTakerFeeAmount)
+ : order.fillableMakerAssetAmount;
+ const fillableTakerAssetAmount = utils.isOrderTakerFeePayableWithTakerAsset(order)
+ ? order.fillableTakerAssetAmount.plus(order.fillableTakerFeeAmount)
+ : order.fillableTakerAssetAmount;
return {
- makerTokensAvailableInBaseUnits: acc.makerTokensAvailableInBaseUnits.plus(
- makerTokensAvailableForCurrentOrder,
- ),
- takerTokensAvailableInBaseUnits: acc.takerTokensAvailableInBaseUnits.plus(
- takerTokensAvailableForCurrentOrder,
- ),
+ makerAssetAvailableInBaseUnits: acc.makerAssetAvailableInBaseUnits.plus(fillableMakerAssetAmount),
+ takerAssetAvailableInBaseUnits: acc.takerAssetAvailableInBaseUnits.plus(fillableTakerAssetAmount),
};
},
{
- makerTokensAvailableInBaseUnits: new BigNumber(0),
- takerTokensAvailableInBaseUnits: new BigNumber(0),
+ makerAssetAvailableInBaseUnits: new BigNumber(0),
+ takerAssetAvailableInBaseUnits: new BigNumber(0),
},
);
-
- // Turn into regular numbers
- return {
- makerTokensAvailableInBaseUnits: liquidityInBigNumbers.makerTokensAvailableInBaseUnits,
- takerTokensAvailableInBaseUnits: liquidityInBigNumbers.takerTokensAvailableInBaseUnits,
- };
+ return liquidityInBigNumbers;
};
diff --git a/packages/asset-swapper/src/utils/market_utils.ts b/packages/asset-swapper/src/utils/market_utils.ts
new file mode 100644
index 0000000000..830f9da922
--- /dev/null
+++ b/packages/asset-swapper/src/utils/market_utils.ts
@@ -0,0 +1,92 @@
+import { BigNumber } from '@0x/utils';
+import * as _ from 'lodash';
+
+import { constants } from '../constants';
+import { MarketOperation, PrunedSignedOrder } from '../types';
+
+import { assert } from './assert';
+import { utils } from './utils';
+
+export const marketUtils = {
+ findOrdersThatCoverTakerAssetFillAmount(
+ sortedOrders: PrunedSignedOrder[],
+ takerAssetFillAmount: BigNumber,
+ slippageBufferAmount: BigNumber = new BigNumber(0),
+ ): { resultOrders: PrunedSignedOrder[]; remainingFillAmount: BigNumber } {
+ return findOrdersThatCoverAssetFillAmount(
+ sortedOrders,
+ takerAssetFillAmount,
+ MarketOperation.Sell,
+ slippageBufferAmount,
+ );
+ },
+ findOrdersThatCoverMakerAssetFillAmount(
+ sortedOrders: PrunedSignedOrder[],
+ makerAssetFillAmount: BigNumber,
+ slippageBufferAmount: BigNumber = new BigNumber(0),
+ ): { resultOrders: PrunedSignedOrder[]; remainingFillAmount: BigNumber } {
+ return findOrdersThatCoverAssetFillAmount(
+ sortedOrders,
+ makerAssetFillAmount,
+ MarketOperation.Buy,
+ slippageBufferAmount,
+ );
+ },
+};
+
+function findOrdersThatCoverAssetFillAmount(
+ sortedOrders: PrunedSignedOrder[],
+ assetFillAmount: BigNumber,
+ operation: MarketOperation,
+ slippageBufferAmount: BigNumber,
+): { resultOrders: PrunedSignedOrder[]; remainingFillAmount: BigNumber } {
+ assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount);
+ // calculate total amount of asset needed to be filled
+ const totalFillAmount = assetFillAmount.plus(slippageBufferAmount);
+ // iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount
+ const result = _.reduce(
+ sortedOrders,
+ ({ resultOrders, remainingFillAmount }, order) => {
+ if (remainingFillAmount.isLessThanOrEqualTo(constants.ZERO_AMOUNT)) {
+ return {
+ resultOrders,
+ remainingFillAmount: constants.ZERO_AMOUNT,
+ };
+ } else {
+ const assetAmountAvailable = getAssetAmountAvailable(order, operation);
+ const shouldIncludeOrder = assetAmountAvailable.gt(constants.ZERO_AMOUNT);
+ // if there is no assetAmountAvailable do not append order to resultOrders
+ // if we have exceeded the total amount we want to fill set remainingFillAmount to 0
+ return {
+ resultOrders: shouldIncludeOrder ? _.concat(resultOrders, order) : resultOrders,
+ remainingFillAmount: BigNumber.max(
+ constants.ZERO_AMOUNT,
+ remainingFillAmount.minus(assetAmountAvailable),
+ ),
+ };
+ }
+ },
+ {
+ resultOrders: [] as PrunedSignedOrder[],
+ remainingFillAmount: totalFillAmount,
+ },
+ );
+
+ return result;
+}
+
+function getAssetAmountAvailable(order: PrunedSignedOrder, operation: MarketOperation): BigNumber {
+ if (operation === MarketOperation.Buy) {
+ if (utils.isOrderTakerFeePayableWithMakerAsset(order)) {
+ return order.fillableMakerAssetAmount.minus(order.fillableTakerFeeAmount);
+ } else {
+ return order.fillableMakerAssetAmount;
+ }
+ } else {
+ if (utils.isOrderTakerFeePayableWithTakerAsset(order)) {
+ return order.fillableTakerAssetAmount.plus(order.fillableTakerFeeAmount);
+ } else {
+ return order.fillableTakerAssetAmount;
+ }
+ }
+}
diff --git a/packages/asset-swapper/src/utils/order_provider_response_processor.ts b/packages/asset-swapper/src/utils/order_provider_response_processor.ts
deleted file mode 100644
index 92442fa52c..0000000000
--- a/packages/asset-swapper/src/utils/order_provider_response_processor.ts
+++ /dev/null
@@ -1,182 +0,0 @@
-import { OrderStatus, OrderValidatorContract } from '@0x/contract-wrappers';
-import { orderCalculationUtils, sortingUtils } from '@0x/order-utils';
-import { RemainingFillableCalculator } from '@0x/order-utils/lib/src/remaining_fillable_calculator';
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import * as _ from 'lodash';
-
-import { constants } from '../constants';
-import {
- OrderProviderResponse,
- OrdersAndFillableAmounts,
- SignedOrderWithRemainingFillableMakerAssetAmount,
- SwapQuoterError,
-} from '../types';
-
-export const orderProviderResponseProcessor = {
- throwIfInvalidResponse(response: OrderProviderResponse, makerAssetData: string, takerAssetData: string): void {
- _.forEach(response.orders, order => {
- if (order.makerAssetData !== makerAssetData || order.takerAssetData !== takerAssetData) {
- throw new Error(SwapQuoterError.InvalidOrderProviderResponse);
- }
- });
- },
- /**
- * Take the responses for the target orders to buy and fee orders and process them.
- * Processing includes:
- * - Drop orders that are expired or not open orders (null taker address)
- * - If an orderValidator is provided, attempt to grab fillable amounts from on-chain otherwise assume completely fillable
- * - Sort by rate
- */
- async processAsync(
- orderProviderResponse: OrderProviderResponse,
- isMakerAssetZrxToken: boolean,
- expiryBufferMs: number,
- orderValidator?: OrderValidatorContract,
- ): Promise {
- // drop orders that are expired or not open
- const filteredOrders = filterOutExpiredAndNonOpenOrders(
- orderProviderResponse.orders,
- expiryBufferMs / constants.ONE_SECOND_MS,
- );
- // set the orders to be sorted equal to the filtered orders
- let unsortedOrders = filteredOrders;
- // if an orderValidator is provided, use on chain information to calculate remaining fillable makerAsset amounts
- if (orderValidator !== undefined) {
- const takerAddresses = _.map(filteredOrders, () => constants.NULL_ADDRESS);
- try {
- const [ordersInfo, tradersInfo] = await orderValidator
- .getOrdersAndTradersInfo(filteredOrders, takerAddresses)
- .callAsync();
- const ordersAndTradersInfo: any[] = ordersInfo.map((orderInfo, index) => {
- const singleOrderAndTraderInfo = {
- orderInfo,
- traderInfo: tradersInfo[index],
- };
- return singleOrderAndTraderInfo;
- });
- // take orders + on chain information and find the valid orders and remaining fillable maker asset amounts
- unsortedOrders = getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
- filteredOrders,
- ordersAndTradersInfo,
- isMakerAssetZrxToken,
- );
- } catch (err) {
- // Sometimes we observe this call to orderValidator fail with response `0x`
- // Because of differences in Parity / Geth implementations, its very hard to tell if this response is a "system error"
- // or a revert. In this case we just swallow these errors and fallback to partial fill information from the SRA.
- // TODO(bmillman): report these errors so we have an idea of how often we're getting these failures.
- }
- }
- // sort orders by rate
- // TODO(bmillman): optimization
- // provide a feeRate to the sorting function to more accurately sort based on the current market for ZRX tokens
- const sortedOrders = isMakerAssetZrxToken
- ? sortingUtils.sortFeeOrdersByFeeAdjustedRate(unsortedOrders)
- : sortingUtils.sortOrdersByFeeAdjustedRate(unsortedOrders);
- // unbundle orders and fillable amounts and compile final result
- const result = unbundleOrdersWithAmounts(sortedOrders);
- return result;
- },
-};
-
-/**
- * Given an array of orders, return a new array with expired and non open orders filtered out.
- */
-function filterOutExpiredAndNonOpenOrders(
- orders: SignedOrderWithRemainingFillableMakerAssetAmount[],
- expiryBufferMs: number,
-): SignedOrderWithRemainingFillableMakerAssetAmount[] {
- const result = _.filter(orders, order => {
- return (
- orderCalculationUtils.isOpenOrder(order) &&
- !orderCalculationUtils.willOrderExpire(order, expiryBufferMs / constants.ONE_SECOND_MS)
- );
- });
- return result;
-}
-
-/**
- * Given an array of orders and corresponding on-chain infos, return a subset of the orders
- * that are still fillable orders with their corresponding remainingFillableMakerAssetAmounts.
- */
-function getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
- inputOrders: SignedOrder[],
- ordersAndTradersInfo: any[],
- isMakerAssetZrxToken: boolean,
-): SignedOrderWithRemainingFillableMakerAssetAmount[] {
- // iterate through the input orders and find the ones that are still fillable
- // for the orders that are still fillable, calculate the remaining fillable maker asset amount
- const result = _.reduce(
- inputOrders,
- (accOrders, order, index) => {
- // get corresponding on-chain state for the order
- const { orderInfo, traderInfo } = ordersAndTradersInfo[index];
- // if the order IS NOT fillable, do not add anything to the accumulations and continue iterating
- if (orderInfo.orderStatus !== OrderStatus.Fillable) {
- return accOrders;
- }
- // if the order IS fillable, add the order and calculate the remaining fillable amount
- const transferrableAssetAmount = BigNumber.min(traderInfo.makerAllowance, traderInfo.makerBalance);
- const transferrableFeeAssetAmount = BigNumber.min(traderInfo.makerZrxAllowance, traderInfo.makerZrxBalance);
- const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
- const remainingMakerAssetAmount = orderCalculationUtils.getMakerFillAmount(
- order,
- remainingTakerAssetAmount,
- );
- const remainingFillableCalculator = new RemainingFillableCalculator(
- order.makerFee,
- order.makerAssetAmount,
- isMakerAssetZrxToken,
- transferrableAssetAmount,
- transferrableFeeAssetAmount,
- remainingMakerAssetAmount,
- );
- const remainingFillableAmount = remainingFillableCalculator.computeRemainingFillable();
- // if the order does not have any remaining fillable makerAsset, do not add anything to the accumulations and continue iterating
- if (remainingFillableAmount.lte(constants.ZERO_AMOUNT)) {
- return accOrders;
- }
- const orderWithRemainingFillableMakerAssetAmount = {
- ...order,
- remainingFillableMakerAssetAmount: remainingFillableAmount,
- };
- const newAccOrders = _.concat(accOrders, orderWithRemainingFillableMakerAssetAmount);
- return newAccOrders;
- },
- [] as SignedOrderWithRemainingFillableMakerAssetAmount[],
- );
- return result;
-}
-
-/**
- * Given an array of orders with remaining fillable maker asset amounts. Unbundle into an instance of OrdersAndRemainingFillableMakerAssetAmounts.
- * If an order is missing a corresponding remainingFillableMakerAssetAmount, assume it is completely fillable.
- */
-function unbundleOrdersWithAmounts(
- ordersWithAmounts: SignedOrderWithRemainingFillableMakerAssetAmount[],
-): OrdersAndFillableAmounts {
- const result = _.reduce(
- ordersWithAmounts,
- (acc, orderWithAmount) => {
- const { orders, remainingFillableMakerAssetAmounts } = acc;
- const { remainingFillableMakerAssetAmount, ...order } = orderWithAmount;
- // if we are still missing a remainingFillableMakerAssetAmount, assume the order is completely fillable
- const newRemainingAmount = remainingFillableMakerAssetAmount || order.makerAssetAmount;
- // if remaining amount is less than or equal to zero, do not add it
- if (newRemainingAmount.lte(constants.ZERO_AMOUNT)) {
- return acc;
- }
- const newAcc = {
- orders: _.concat(orders, order),
- remainingFillableMakerAssetAmounts: _.concat(remainingFillableMakerAssetAmounts, newRemainingAmount),
- };
- return newAcc;
- },
- {
- orders: [] as SignedOrder[],
- remainingFillableMakerAssetAmounts: [] as BigNumber[],
- },
- );
- return result;
-}
diff --git a/packages/asset-swapper/src/utils/order_prune_utils.ts b/packages/asset-swapper/src/utils/order_prune_utils.ts
new file mode 100644
index 0000000000..b5fbcdc580
--- /dev/null
+++ b/packages/asset-swapper/src/utils/order_prune_utils.ts
@@ -0,0 +1,96 @@
+import { DevUtilsContract } from '@0x/contracts-dev-utils';
+import { orderCalculationUtils } from '@0x/order-utils';
+import { OrderStatus, SignedOrder } from '@0x/types';
+import * as _ from 'lodash';
+
+import { constants } from '../constants';
+import { OrderPrunerOnChainMetadata, OrderPrunerOpts, OrderPrunerPermittedFeeTypes, PrunedSignedOrder } from '../types';
+import { utils } from '../utils/utils';
+
+export class OrderPruner {
+ public readonly expiryBufferMs: number;
+ public readonly permittedOrderFeeTypes: Set;
+ private readonly _devUtils: DevUtilsContract;
+
+ // TODO(dave4506): OrderPruneCalculator can be more powerful if it takes in a specified takerAddress
+ constructor(devUtils: DevUtilsContract, opts: Partial = {}) {
+ const { expiryBufferMs, permittedOrderFeeTypes } = _.assign({}, constants.DEFAULT_ORDER_PRUNER_OPTS, opts);
+
+ this.expiryBufferMs = expiryBufferMs;
+ this.permittedOrderFeeTypes = permittedOrderFeeTypes;
+ this._devUtils = devUtils;
+ }
+
+ public async pruneSignedOrdersAsync(signedOrders: SignedOrder[]): Promise {
+ const unsortedOrders = this._filterForUsableOrders(signedOrders, this.expiryBufferMs);
+
+ const signatures = _.map(unsortedOrders, o => o.signature);
+ const [ordersInfo, fillableTakerAssetAmounts, isValidSignatures] = await this._devUtils
+ .getOrderRelevantStates(unsortedOrders, signatures)
+ .callAsync();
+ const ordersOnChainMetadata: OrderPrunerOnChainMetadata[] = ordersInfo.map((orderInfo, index) => {
+ return {
+ ...orderInfo,
+ fillableTakerAssetAmount: fillableTakerAssetAmounts[index],
+ isValidSignature: isValidSignatures[index],
+ };
+ });
+ // take orders + on chain information and find the valid orders and fillable makerAsset or takerAsset amounts
+ const prunedOrders = this._filterForFillableAndPermittedFeeTypeOrders(unsortedOrders, ordersOnChainMetadata);
+
+ return prunedOrders;
+ }
+
+ // tslint:disable-next-line: prefer-function-over-method
+ private _filterForFillableAndPermittedFeeTypeOrders(
+ orders: SignedOrder[],
+ ordersOnChainMetadata: OrderPrunerOnChainMetadata[],
+ ): PrunedSignedOrder[] {
+ const result = _.chain(orders)
+ .filter(
+ (order: SignedOrder, index: number): boolean => {
+ const { isValidSignature, orderStatus } = ordersOnChainMetadata[index];
+ return (
+ isValidSignature &&
+ orderStatus === OrderStatus.Fillable &&
+ ((this.permittedOrderFeeTypes.has(OrderPrunerPermittedFeeTypes.NoFees) &&
+ order.takerFee.eq(constants.ZERO_AMOUNT)) ||
+ (this.permittedOrderFeeTypes.has(OrderPrunerPermittedFeeTypes.TakerDenominatedTakerFee) &&
+ utils.isOrderTakerFeePayableWithTakerAsset(order)) ||
+ (this.permittedOrderFeeTypes.has(OrderPrunerPermittedFeeTypes.MakerDenominatedTakerFee) &&
+ utils.isOrderTakerFeePayableWithMakerAsset(order)))
+ );
+ },
+ )
+ .map(
+ (order: SignedOrder, index: number): PrunedSignedOrder => {
+ const { fillableTakerAssetAmount } = ordersOnChainMetadata[index];
+ return {
+ ...order,
+ fillableTakerAssetAmount,
+ fillableMakerAssetAmount: orderCalculationUtils.getMakerFillAmount(
+ order,
+ fillableTakerAssetAmount,
+ ),
+ fillableTakerFeeAmount: orderCalculationUtils.getTakerFeeAmount(
+ order,
+ fillableTakerAssetAmount,
+ ),
+ };
+ },
+ )
+ .value();
+ return result;
+ }
+
+ // tslint:disable-next-line: prefer-function-over-method
+ private _filterForUsableOrders(orders: SignedOrder[], expiryBufferMs: number): SignedOrder[] {
+ const result = _.filter(orders, order => {
+ return (
+ orderCalculationUtils.isOpenOrder(order) &&
+ !orderCalculationUtils.willOrderExpire(order, expiryBufferMs / constants.ONE_SECOND_MS)
+ );
+ });
+ return result;
+ }
+}
diff --git a/packages/asset-swapper/src/utils/protocol_fee_utils.ts b/packages/asset-swapper/src/utils/protocol_fee_utils.ts
new file mode 100644
index 0000000000..784d5209ae
--- /dev/null
+++ b/packages/asset-swapper/src/utils/protocol_fee_utils.ts
@@ -0,0 +1,31 @@
+import { Order } from '@0x/types';
+import { BigNumber } from '@0x/utils';
+import * as _ from 'lodash';
+
+import { constants } from '../constants';
+import { SwapQuoterError } from '../types';
+
+// tslint:disable:no-unnecessary-type-assertion
+export const protocolFeeUtils = {
+ /**
+ * Gets 'fast' gas price from Eth Gas Station.
+ */
+ async getGasPriceEstimationOrThrowAsync(): Promise {
+ try {
+ const res = await fetch(`${constants.ETH_GAS_STATION_API_BASE_URL}/json/ethgasAPI.json`);
+ const gasInfo = await res.json();
+ // Eth Gas Station result is gwei * 10
+ // tslint:disable-next-line:custom-no-magic-numbers
+ return new BigNumber(gasInfo.fast / 10);
+ } catch (e) {
+ throw new Error(SwapQuoterError.NoGasPriceProvidedOrEstimated);
+ }
+ },
+ /**
+ * Calculates protocol fee with protofol fee multiplier for each fill.
+ */
+ calculateWorstCaseProtocolFee(orders: T[], gasPrice: BigNumber): BigNumber {
+ const protocolFee = new BigNumber(orders.length * constants.PROTOCOL_FEE_MULTIPLIER).times(gasPrice);
+ return protocolFee;
+ },
+};
diff --git a/packages/asset-swapper/src/utils/sorting_utils.ts b/packages/asset-swapper/src/utils/sorting_utils.ts
new file mode 100644
index 0000000000..4f41944379
--- /dev/null
+++ b/packages/asset-swapper/src/utils/sorting_utils.ts
@@ -0,0 +1,29 @@
+import { schemas } from '@0x/json-schemas';
+import { Order } from '@0x/types';
+import { BigNumber } from '@0x/utils';
+import * as _ from 'lodash';
+
+import { assert } from './assert';
+import { utils } from './utils';
+
+export const sortingUtils = {
+ sortOrders(orders: T[]): T[] {
+ assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
+ assert.isValidOrdersForSwapQuoter('orders', orders);
+ const copiedOrders = _.cloneDeep(orders);
+ copiedOrders.sort((firstOrder, secondOrder) => {
+ const firstOrderRate = getTakerFeeAdjustedRateOfOrder(firstOrder);
+ const secondOrderRate = getTakerFeeAdjustedRateOfOrder(secondOrder);
+ return firstOrderRate.comparedTo(secondOrderRate);
+ });
+ return copiedOrders;
+ },
+};
+
+function getTakerFeeAdjustedRateOfOrder(order: Order): BigNumber {
+ const [adjustedMakerAssetAmount, adjustedTakerAssetAmount] = utils.getAdjustedMakerAndTakerAmountsFromTakerFees(
+ order,
+ );
+ const rate = adjustedTakerAssetAmount.div(adjustedMakerAssetAmount);
+ return rate;
+}
diff --git a/packages/asset-swapper/src/utils/swap_quote_calculator.ts b/packages/asset-swapper/src/utils/swap_quote_calculator.ts
index 9ae521f355..ec2ac25981 100644
--- a/packages/asset-swapper/src/utils/swap_quote_calculator.ts
+++ b/packages/asset-swapper/src/utils/swap_quote_calculator.ts
@@ -1,5 +1,4 @@
-import { marketUtils, orderCalculationUtils, SignedOrder } from '@0x/order-utils';
-import { MarketOperation } from '@0x/types';
+import { orderCalculationUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
@@ -7,106 +6,75 @@ import { constants } from '../constants';
import { InsufficientAssetLiquidityError } from '../errors';
import {
MarketBuySwapQuote,
+ MarketOperation,
MarketSellSwapQuote,
- OrdersAndFillableAmounts,
+ PrunedSignedOrder,
SwapQuote,
SwapQuoteInfo,
- SwapQuoterError,
} from '../types';
+import { marketUtils } from './market_utils';
+import { protocolFeeUtils } from './protocol_fee_utils';
+import { utils } from './utils';
+
// Calculates a swap quote for orders
export const swapQuoteCalculator = {
calculateMarketSellSwapQuote(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
+ prunedOrders: PrunedSignedOrder[],
takerAssetFillAmount: BigNumber,
slippagePercentage: number,
- isMakerAssetZrxToken: boolean,
- shouldDisableFeeOrderCalculations: boolean,
+ gasPrice: BigNumber,
): MarketSellSwapQuote {
return calculateSwapQuote(
- ordersAndFillableAmounts,
- feeOrdersAndFillableAmounts,
+ prunedOrders,
takerAssetFillAmount,
slippagePercentage,
- isMakerAssetZrxToken,
- shouldDisableFeeOrderCalculations,
+ gasPrice,
MarketOperation.Sell,
) as MarketSellSwapQuote;
},
calculateMarketBuySwapQuote(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- makerAssetFillAmount: BigNumber,
+ prunedOrders: PrunedSignedOrder[],
+ takerAssetFillAmount: BigNumber,
slippagePercentage: number,
- isMakerAssetZrxToken: boolean,
- shouldDisableFeeOrderCalculations: boolean,
+ gasPrice: BigNumber,
): MarketBuySwapQuote {
return calculateSwapQuote(
- ordersAndFillableAmounts,
- feeOrdersAndFillableAmounts,
- makerAssetFillAmount,
+ prunedOrders,
+ takerAssetFillAmount,
slippagePercentage,
- isMakerAssetZrxToken,
- shouldDisableFeeOrderCalculations,
+ gasPrice,
MarketOperation.Buy,
) as MarketBuySwapQuote;
},
};
function calculateSwapQuote(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
+ prunedOrders: PrunedSignedOrder[],
assetFillAmount: BigNumber,
slippagePercentage: number,
- isMakerAssetZrxToken: boolean,
- shouldDisableFeeOrderCalculations: boolean,
+ gasPrice: BigNumber,
marketOperation: MarketOperation,
): SwapQuote {
- const orders = ordersAndFillableAmounts.orders;
- const remainingFillableMakerAssetAmounts = ordersAndFillableAmounts.remainingFillableMakerAssetAmounts;
- const remainingFillableTakerAssetAmounts = remainingFillableMakerAssetAmounts.map(
- (makerAssetAmount: BigNumber, index: number) => {
- return orderCalculationUtils.getTakerFillAmount(orders[index], makerAssetAmount);
- },
- );
- const feeOrders = feeOrdersAndFillableAmounts.orders;
- const remainingFillableFeeAmounts = feeOrdersAndFillableAmounts.remainingFillableMakerAssetAmounts;
-
const slippageBufferAmount = assetFillAmount.multipliedBy(slippagePercentage).integerValue();
- let resultOrders: SignedOrder[];
+ let resultOrders: PrunedSignedOrder[];
let remainingFillAmount: BigNumber;
- let ordersRemainingFillableMakerAssetAmounts: BigNumber[];
if (marketOperation === MarketOperation.Buy) {
// find the orders that cover the desired assetBuyAmount (with slippage)
- ({
- resultOrders,
- remainingFillAmount,
- ordersRemainingFillableMakerAssetAmounts,
- } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(orders, assetFillAmount, {
- remainingFillableMakerAssetAmounts,
+ ({ resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ prunedOrders,
+ assetFillAmount,
slippageBufferAmount,
- }));
+ ));
} else {
- let ordersRemainingFillableTakerAssetAmounts: BigNumber[];
// find the orders that cover the desired assetBuyAmount (with slippage)
- ({
- resultOrders,
- remainingFillAmount,
- ordersRemainingFillableTakerAssetAmounts,
- } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(orders, assetFillAmount, {
- remainingFillableTakerAssetAmounts,
+ ({ resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ prunedOrders,
+ assetFillAmount,
slippageBufferAmount,
- }));
-
- ordersRemainingFillableMakerAssetAmounts = _.map(
- ordersRemainingFillableTakerAssetAmounts,
- (takerAssetAmount: BigNumber, index: number) => {
- return orderCalculationUtils.getMakerFillAmount(resultOrders[index], takerAssetAmount);
- },
- );
+ ));
}
// if we do not have enough orders to cover the desired assetBuyAmount, throw
@@ -126,60 +94,16 @@ function calculateSwapQuote(
throw new InsufficientAssetLiquidityError(amountAvailableToFillConsideringSlippage);
}
- // if we are not buying ZRX:
- // given the orders calculated above, find the fee-orders that cover the desired assetBuyAmount (with slippage)
- // TODO(bmillman): optimization
- // update this logic to find the minimum amount of feeOrders to cover the worst case as opposed to
- // finding order that cover all fees, this will help with estimating ETH and minimizing gas usage
- let resultFeeOrders = [] as SignedOrder[];
- let feeOrdersRemainingFillableMakerAssetAmounts = [] as BigNumber[];
- if (!shouldDisableFeeOrderCalculations && !isMakerAssetZrxToken) {
- const feeOrdersAndRemainingFeeAmount = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
- resultOrders,
- feeOrders,
- {
- remainingFillableMakerAssetAmounts: ordersRemainingFillableMakerAssetAmounts,
- remainingFillableFeeAmounts,
- },
- );
- // if we do not have enough feeOrders to cover the fees, throw
- if (feeOrdersAndRemainingFeeAmount.remainingFeeAmount.gt(constants.ZERO_AMOUNT)) {
- throw new Error(SwapQuoterError.InsufficientZrxLiquidity);
- }
- resultFeeOrders = feeOrdersAndRemainingFeeAmount.resultFeeOrders;
- feeOrdersRemainingFillableMakerAssetAmounts =
- feeOrdersAndRemainingFeeAmount.feeOrdersRemainingFillableMakerAssetAmounts;
- }
-
// assetData information for the result
- const takerAssetData = orders[0].takerAssetData;
- const makerAssetData = orders[0].makerAssetData;
+ const takerAssetData = resultOrders[0].takerAssetData;
+ const makerAssetData = resultOrders[0].makerAssetData;
- // compile the resulting trimmed set of orders for makerAsset and feeOrders that are needed for assetBuyAmount
- const trimmedOrdersAndFillableAmounts: OrdersAndFillableAmounts = {
- orders: resultOrders,
- remainingFillableMakerAssetAmounts: ordersRemainingFillableMakerAssetAmounts,
- };
- const trimmedFeeOrdersAndFillableAmounts: OrdersAndFillableAmounts = {
- orders: resultFeeOrders,
- remainingFillableMakerAssetAmounts: feeOrdersRemainingFillableMakerAssetAmounts,
- };
-
- const bestCaseQuoteInfo = calculateQuoteInfo(
- trimmedOrdersAndFillableAmounts,
- trimmedFeeOrdersAndFillableAmounts,
- assetFillAmount,
- isMakerAssetZrxToken,
- shouldDisableFeeOrderCalculations,
- marketOperation,
- );
+ const bestCaseQuoteInfo = calculateQuoteInfo(resultOrders, assetFillAmount, gasPrice, marketOperation);
// in order to calculate the maxRate, reverse the ordersAndFillableAmounts such that they are sorted from worst rate to best rate
const worstCaseQuoteInfo = calculateQuoteInfo(
- reverseOrdersAndFillableAmounts(trimmedOrdersAndFillableAmounts),
- reverseOrdersAndFillableAmounts(trimmedFeeOrdersAndFillableAmounts),
+ _.reverse(_.clone(resultOrders)),
assetFillAmount,
- isMakerAssetZrxToken,
- shouldDisableFeeOrderCalculations,
+ gasPrice,
marketOperation,
);
@@ -187,7 +111,6 @@ function calculateSwapQuote(
takerAssetData,
makerAssetData,
orders: resultOrders,
- feeOrders: resultFeeOrders,
bestCaseQuoteInfo,
worstCaseQuoteInfo,
};
@@ -208,199 +131,159 @@ function calculateSwapQuote(
}
function calculateQuoteInfo(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- tokenAmount: BigNumber,
- isMakerAssetZrxToken: boolean,
- shouldDisableFeeOrderCalculations: boolean,
- marketOperation: MarketOperation,
+ prunedOrders: PrunedSignedOrder[],
+ assetFillAmount: BigNumber,
+ gasPrice: BigNumber,
+ operation: MarketOperation,
): SwapQuoteInfo {
- // find the total eth and zrx needed to buy assetAmount from the resultOrders from left to right
- let makerTokenAmount = marketOperation === MarketOperation.Buy ? tokenAmount : constants.ZERO_AMOUNT;
- let takerTokenAmount = marketOperation === MarketOperation.Sell ? tokenAmount : constants.ZERO_AMOUNT;
- let zrxTakerTokenAmount = constants.ZERO_AMOUNT;
-
- if (isMakerAssetZrxToken) {
- if (marketOperation === MarketOperation.Buy) {
- takerTokenAmount = findTakerTokenAmountNeededToBuyZrx(ordersAndFillableAmounts, makerTokenAmount);
- } else {
- makerTokenAmount = findZrxTokenAmountFromSellingTakerTokenAmount(
- ordersAndFillableAmounts,
- takerTokenAmount,
- );
- }
+ if (operation === MarketOperation.Buy) {
+ return calculateMarketBuyQuoteInfo(prunedOrders, assetFillAmount, gasPrice);
} else {
- const findTokenAndZrxAmount =
- marketOperation === MarketOperation.Buy
- ? findTakerTokenAndZrxAmountNeededToBuyAsset
- : findMakerTokenAmountReceivedAndZrxAmountNeededToSellAsset;
- // find eth and zrx amounts needed to buy
- const tokenAndZrxAmountToBuyAsset = findTokenAndZrxAmount(
- ordersAndFillableAmounts,
- marketOperation === MarketOperation.Buy ? makerTokenAmount : takerTokenAmount,
- );
- if (marketOperation === MarketOperation.Buy) {
- takerTokenAmount = tokenAndZrxAmountToBuyAsset[0];
- } else {
- makerTokenAmount = tokenAndZrxAmountToBuyAsset[0];
- }
- const zrxAmountToBuyAsset = tokenAndZrxAmountToBuyAsset[1];
- // find eth amount needed to buy zrx
- zrxTakerTokenAmount = shouldDisableFeeOrderCalculations
- ? constants.ZERO_AMOUNT
- : findTakerTokenAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset);
+ return calculateMarketSellQuoteInfo(prunedOrders, assetFillAmount, gasPrice);
}
-
- const feeTakerTokenAmount = zrxTakerTokenAmount;
-
- // eth amount needed in total is the sum of the amount needed for the asset and the amount needed for fees
- const totalTakerTokenAmount = takerTokenAmount.plus(feeTakerTokenAmount);
- return {
- makerTokenAmount,
- takerTokenAmount,
- feeTakerTokenAmount,
- totalTakerTokenAmount,
- };
-}
-// given an OrdersAndFillableAmounts, reverse the orders and remainingFillableMakerAssetAmounts properties
-function reverseOrdersAndFillableAmounts(ordersAndFillableAmounts: OrdersAndFillableAmounts): OrdersAndFillableAmounts {
- const ordersCopy = _.clone(ordersAndFillableAmounts.orders);
- const remainingFillableMakerAssetAmountsCopy = _.clone(ordersAndFillableAmounts.remainingFillableMakerAssetAmounts);
- return {
- orders: ordersCopy.reverse(),
- remainingFillableMakerAssetAmounts: remainingFillableMakerAssetAmountsCopy.reverse(),
- };
}
-function findZrxTokenAmountFromSellingTakerTokenAmount(
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
+function calculateMarketSellQuoteInfo(
+ prunedOrders: PrunedSignedOrder[],
takerAssetSellAmount: BigNumber,
-): BigNumber {
- const { orders, remainingFillableMakerAssetAmounts } = feeOrdersAndFillableAmounts;
+ gasPrice: BigNumber,
+): SwapQuoteInfo {
const result = _.reduce(
- orders,
- (acc, order, index) => {
- const { totalZrxTokenAmount, remainingTakerAssetFillAmount } = acc;
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- const remainingFillableTakerAssetAmount = orderCalculationUtils.getTakerFillAmount(
- order,
- remainingFillableMakerAssetAmount,
+ prunedOrders,
+ (acc, order) => {
+ const {
+ totalMakerAssetAmount,
+ totalTakerAssetAmount,
+ totalFeeTakerAssetAmount,
+ remainingTakerAssetFillAmount,
+ } = acc;
+ const [
+ adjustedFillableMakerAssetAmount,
+ adjustedFillableTakerAssetAmount,
+ ] = utils.getAdjustedFillableMakerAndTakerAmountsFromTakerFees(order);
+ const takerAssetAmountWithFees = BigNumber.min(
+ remainingTakerAssetFillAmount,
+ adjustedFillableTakerAssetAmount,
);
- const takerFillAmount = BigNumber.min(remainingTakerAssetFillAmount, remainingFillableTakerAssetAmount);
- const makerFillAmount = orderCalculationUtils.getMakerFillAmount(order, takerFillAmount);
- const feeAmount = orderCalculationUtils.getTakerFeeAmount(order, takerFillAmount);
+ const { takerAssetAmount, feeTakerAssetAmount } = getTakerAssetAmountBreakDown(
+ order,
+ takerAssetAmountWithFees,
+ );
+ const makerAssetAmount = takerAssetAmountWithFees
+ .div(adjustedFillableTakerAssetAmount)
+ .multipliedBy(adjustedFillableMakerAssetAmount)
+ .integerValue(BigNumber.ROUND_CEIL);
return {
- totalZrxTokenAmount: totalZrxTokenAmount.plus(makerFillAmount).minus(feeAmount),
+ totalMakerAssetAmount: totalMakerAssetAmount.plus(makerAssetAmount),
+ totalTakerAssetAmount: totalTakerAssetAmount.plus(takerAssetAmount),
+ totalFeeTakerAssetAmount: totalFeeTakerAssetAmount.plus(feeTakerAssetAmount),
remainingTakerAssetFillAmount: BigNumber.max(
constants.ZERO_AMOUNT,
- remainingTakerAssetFillAmount.minus(takerFillAmount),
+ remainingTakerAssetFillAmount.minus(takerAssetAmountWithFees),
),
};
},
{
- totalZrxTokenAmount: constants.ZERO_AMOUNT,
+ totalMakerAssetAmount: constants.ZERO_AMOUNT,
+ totalTakerAssetAmount: constants.ZERO_AMOUNT,
+ totalFeeTakerAssetAmount: constants.ZERO_AMOUNT,
remainingTakerAssetFillAmount: takerAssetSellAmount,
},
);
- return result.totalZrxTokenAmount;
+ return {
+ feeTakerAssetAmount: result.totalFeeTakerAssetAmount,
+ takerAssetAmount: result.totalTakerAssetAmount,
+ totalTakerAssetAmount: result.totalFeeTakerAssetAmount.plus(result.totalTakerAssetAmount),
+ makerAssetAmount: result.totalMakerAssetAmount,
+ protocolFeeInEthAmount: protocolFeeUtils.calculateWorstCaseProtocolFee(prunedOrders, gasPrice),
+ };
}
-function findTakerTokenAmountNeededToBuyZrx(
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- zrxBuyAmount: BigNumber,
-): BigNumber {
- const { orders, remainingFillableMakerAssetAmounts } = feeOrdersAndFillableAmounts;
- const result = _.reduce(
- orders,
- (acc, order, index) => {
- const { totalTakerTokenAmount, remainingZrxBuyAmount } = acc;
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- const makerFillAmount = BigNumber.min(remainingZrxBuyAmount, remainingFillableMakerAssetAmount);
- const [takerFillAmount, adjustedMakerFillAmount] = orderCalculationUtils.getTakerFillAmountForFeeOrder(
- order,
- makerFillAmount,
- );
- const extraFeeAmount = remainingFillableMakerAssetAmount.isGreaterThanOrEqualTo(adjustedMakerFillAmount)
- ? constants.ZERO_AMOUNT
- : adjustedMakerFillAmount.minus(makerFillAmount);
- return {
- totalTakerTokenAmount: totalTakerTokenAmount.plus(takerFillAmount),
- remainingZrxBuyAmount: BigNumber.max(
- constants.ZERO_AMOUNT,
- remainingZrxBuyAmount.minus(makerFillAmount).plus(extraFeeAmount),
- ),
- };
- },
- {
- totalTakerTokenAmount: constants.ZERO_AMOUNT,
- remainingZrxBuyAmount: zrxBuyAmount,
- },
- );
- return result.totalTakerTokenAmount;
-}
-
-function findTakerTokenAndZrxAmountNeededToBuyAsset(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
+function calculateMarketBuyQuoteInfo(
+ prunedOrders: PrunedSignedOrder[],
makerAssetBuyAmount: BigNumber,
-): [BigNumber, BigNumber] {
- const { orders, remainingFillableMakerAssetAmounts } = ordersAndFillableAmounts;
+ gasPrice: BigNumber,
+): SwapQuoteInfo {
const result = _.reduce(
- orders,
- (acc, order, index) => {
- const { totalTakerTokenAmount, totalZrxAmount, remainingmakerAssetFillAmount } = acc;
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- const makerFillAmount = BigNumber.min(acc.remainingmakerAssetFillAmount, remainingFillableMakerAssetAmount);
- const takerFillAmount = orderCalculationUtils.getTakerFillAmount(order, makerFillAmount);
- const takerFeeAmount = orderCalculationUtils.getTakerFeeAmount(order, takerFillAmount);
+ prunedOrders,
+ (acc, order) => {
+ const {
+ totalMakerAssetAmount,
+ totalTakerAssetAmount,
+ totalFeeTakerAssetAmount,
+ remainingMakerAssetFillAmount,
+ } = acc;
+ const [
+ adjustedFillableMakerAssetAmount,
+ adjustedFillableTakerAssetAmount,
+ ] = utils.getAdjustedFillableMakerAndTakerAmountsFromTakerFees(order);
+ const makerFillAmount = BigNumber.min(remainingMakerAssetFillAmount, adjustedFillableMakerAssetAmount);
+ const takerAssetAmountWithFees = makerFillAmount
+ .div(adjustedFillableMakerAssetAmount)
+ .multipliedBy(adjustedFillableTakerAssetAmount)
+ .integerValue(BigNumber.ROUND_CEIL);
+ const { takerAssetAmount, feeTakerAssetAmount } = getTakerAssetAmountBreakDown(
+ order,
+ takerAssetAmountWithFees,
+ );
return {
- totalTakerTokenAmount: totalTakerTokenAmount.plus(takerFillAmount),
- totalZrxAmount: totalZrxAmount.plus(takerFeeAmount),
- remainingmakerAssetFillAmount: BigNumber.max(
+ totalMakerAssetAmount: totalMakerAssetAmount.plus(makerFillAmount),
+ totalTakerAssetAmount: totalTakerAssetAmount.plus(takerAssetAmount),
+ totalFeeTakerAssetAmount: totalFeeTakerAssetAmount.plus(feeTakerAssetAmount),
+ remainingMakerAssetFillAmount: BigNumber.max(
constants.ZERO_AMOUNT,
- remainingmakerAssetFillAmount.minus(makerFillAmount),
+ remainingMakerAssetFillAmount.minus(makerFillAmount),
),
};
},
{
- totalTakerTokenAmount: constants.ZERO_AMOUNT,
- totalZrxAmount: constants.ZERO_AMOUNT,
- remainingmakerAssetFillAmount: makerAssetBuyAmount,
+ totalMakerAssetAmount: constants.ZERO_AMOUNT,
+ totalTakerAssetAmount: constants.ZERO_AMOUNT,
+ totalFeeTakerAssetAmount: constants.ZERO_AMOUNT,
+ remainingMakerAssetFillAmount: makerAssetBuyAmount,
},
);
- return [result.totalTakerTokenAmount, result.totalZrxAmount];
+ return {
+ feeTakerAssetAmount: result.totalFeeTakerAssetAmount,
+ takerAssetAmount: result.totalTakerAssetAmount,
+ totalTakerAssetAmount: result.totalFeeTakerAssetAmount.plus(result.totalTakerAssetAmount),
+ makerAssetAmount: result.totalMakerAssetAmount,
+ protocolFeeInEthAmount: protocolFeeUtils.calculateWorstCaseProtocolFee(prunedOrders, gasPrice),
+ };
}
-function findMakerTokenAmountReceivedAndZrxAmountNeededToSellAsset(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- takerAssetSellAmount: BigNumber,
-): [BigNumber, BigNumber] {
- const { orders, remainingFillableMakerAssetAmounts } = ordersAndFillableAmounts;
- const result = _.reduce(
- orders,
- (acc, order, index) => {
- const { totalMakerTokenAmount, totalZrxAmount, remainingTakerAssetFillAmount } = acc;
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- const remainingFillableTakerAssetAmount = orderCalculationUtils.getTakerFillAmount(
- order,
- remainingFillableMakerAssetAmount,
- );
- const takerFillAmount = BigNumber.min(acc.remainingTakerAssetFillAmount, remainingFillableTakerAssetAmount);
- const makerFillAmount = orderCalculationUtils.getMakerFillAmount(order, takerFillAmount);
- const takerFeeAmount = orderCalculationUtils.getTakerFeeAmount(order, takerFillAmount);
+function getTakerAssetAmountBreakDown(
+ order: PrunedSignedOrder,
+ takerAssetAmountWithFees: BigNumber,
+): { feeTakerAssetAmount: BigNumber; takerAssetAmount: BigNumber } {
+ if (utils.isOrderTakerFeePayableWithTakerAsset(order)) {
+ const adjustedTakerAssetAmount = order.takerAssetAmount.plus(order.takerFee);
+ const filledRatio = takerAssetAmountWithFees.div(adjustedTakerAssetAmount);
+ const takerAssetAmount = filledRatio.multipliedBy(order.takerAssetAmount).integerValue(BigNumber.ROUND_CEIL);
+ return {
+ takerAssetAmount,
+ feeTakerAssetAmount: takerAssetAmountWithFees.minus(takerAssetAmount),
+ };
+ } else if (utils.isOrderTakerFeePayableWithMakerAsset(order)) {
+ if (takerAssetAmountWithFees.isZero()) {
return {
- totalMakerTokenAmount: totalMakerTokenAmount.plus(makerFillAmount),
- totalZrxAmount: totalZrxAmount.plus(takerFeeAmount),
- remainingTakerAssetFillAmount: BigNumber.max(
- constants.ZERO_AMOUNT,
- remainingTakerAssetFillAmount.minus(takerFillAmount),
- ),
+ takerAssetAmount: constants.ZERO_AMOUNT,
+ feeTakerAssetAmount: constants.ZERO_AMOUNT,
};
- },
- {
- totalMakerTokenAmount: constants.ZERO_AMOUNT,
- totalZrxAmount: constants.ZERO_AMOUNT,
- remainingTakerAssetFillAmount: takerAssetSellAmount,
- },
- );
- return [result.totalMakerTokenAmount, result.totalZrxAmount];
+ }
+ const takerFeeAmount = orderCalculationUtils.getTakerFeeAmount(order, takerAssetAmountWithFees);
+ const makerAssetFillAmount = orderCalculationUtils.getMakerFillAmount(order, takerAssetAmountWithFees);
+ const takerAssetAmount = takerFeeAmount
+ .div(makerAssetFillAmount)
+ .multipliedBy(takerAssetAmountWithFees)
+ .integerValue(BigNumber.ROUND_CEIL);
+ return {
+ takerAssetAmount,
+ feeTakerAssetAmount: takerAssetAmountWithFees.minus(takerAssetAmount),
+ };
+ }
+ return {
+ feeTakerAssetAmount: constants.ZERO_AMOUNT,
+ takerAssetAmount: takerAssetAmountWithFees,
+ };
}
diff --git a/packages/asset-swapper/src/utils/swap_quote_consumer_utils.ts b/packages/asset-swapper/src/utils/swap_quote_consumer_utils.ts
index 87be11f339..5a1bf191ff 100644
--- a/packages/asset-swapper/src/utils/swap_quote_consumer_utils.ts
+++ b/packages/asset-swapper/src/utils/swap_quote_consumer_utils.ts
@@ -1,5 +1,7 @@
-import { ContractWrappers } from '@0x/contract-wrappers';
-import { MarketOperation, SignedOrder } from '@0x/types';
+import { ContractAddresses } from '@0x/contract-addresses';
+import { DevUtilsContract } from '@0x/contracts-dev-utils';
+import { WETH9Contract } from '@0x/contracts-erc20';
+import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { SupportedProvider, Web3Wrapper } from '@0x/web3-wrapper';
import { Provider } from 'ethereum-types';
@@ -47,19 +49,17 @@ export const swapQuoteConsumerUtils = {
},
async getEthAndWethBalanceAsync(
provider: SupportedProvider,
- contractWrappers: ContractWrappers,
+ contractAddresses: ContractAddresses,
takerAddress: string,
): Promise<[BigNumber, BigNumber]> {
+ const weth = new WETH9Contract(contractAddresses.etherToken, provider);
const web3Wrapper = new Web3Wrapper(provider);
const ethBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const wethBalance = await contractWrappers.weth9.balanceOf(takerAddress).callAsync();
+ const wethBalance = await weth.balanceOf(takerAddress).callAsync();
return [ethBalance, wethBalance];
},
isValidForwarderSwapQuote(swapQuote: SwapQuote, wethAssetData: string): boolean {
- return (
- swapQuoteConsumerUtils.isValidForwarderSignedOrders(swapQuote.orders, wethAssetData) &&
- swapQuoteConsumerUtils.isValidForwarderSignedOrders(swapQuote.feeOrders, wethAssetData)
- );
+ return swapQuoteConsumerUtils.isValidForwarderSignedOrders(swapQuote.orders, wethAssetData);
},
isValidForwarderSignedOrders(orders: SignedOrder[], wethAssetData: string): boolean {
return _.every(orders, order => swapQuoteConsumerUtils.isValidForwarderSignedOrder(order, wethAssetData));
@@ -67,35 +67,25 @@ export const swapQuoteConsumerUtils = {
isValidForwarderSignedOrder(order: SignedOrder, wethAssetData: string): boolean {
return order.takerAssetData === wethAssetData;
},
- optimizeOrdersForMarketExchangeOperation(orders: SignedOrder[], operation: MarketOperation): SignedOrder[] {
- return _.map(orders, (order: SignedOrder, index: number) => {
- const optimizedOrder = _.clone(order);
- if (operation === MarketOperation.Sell && index !== 0) {
- optimizedOrder.takerAssetData = constants.NULL_BYTES;
- } else if (index !== 0) {
- optimizedOrder.makerAssetData = constants.NULL_BYTES;
- }
- return optimizedOrder;
- });
- },
async getExtensionContractTypeForSwapQuoteAsync(
quote: SwapQuote,
- contractWrappers: ContractWrappers,
+ contractAddresses: ContractAddresses,
provider: Provider,
opts: Partial,
): Promise {
- const wethAssetData = await contractWrappers.devUtils
- .encodeERC20AssetData(contractWrappers.contractAddresses.etherToken)
- .callAsync();
+ const devUtils = new DevUtilsContract(contractAddresses.devUtils, provider);
+ const wethAssetData = await devUtils.encodeERC20AssetData(contractAddresses.etherToken).callAsync();
if (swapQuoteConsumerUtils.isValidForwarderSwapQuote(quote, wethAssetData)) {
if (opts.takerAddress !== undefined) {
assert.isETHAddressHex('takerAddress', opts.takerAddress);
}
- const ethAmount = opts.ethAmount || quote.worstCaseQuoteInfo.totalTakerTokenAmount;
+ const ethAmount =
+ opts.ethAmount ||
+ quote.worstCaseQuoteInfo.takerAssetAmount.plus(quote.worstCaseQuoteInfo.protocolFeeInEthAmount);
const takerAddress = await swapQuoteConsumerUtils.getTakerAddressAsync(provider, opts);
const takerEthAndWethBalance =
takerAddress !== undefined
- ? await swapQuoteConsumerUtils.getEthAndWethBalanceAsync(provider, contractWrappers, takerAddress)
+ ? await swapQuoteConsumerUtils.getEthAndWethBalanceAsync(provider, contractAddresses, takerAddress)
: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT];
// TODO(david): when considering if there is enough Eth balance, should account for gas costs.
const isEnoughEthAndWethBalance = _.map(takerEthAndWethBalance, (balance: BigNumber) =>
diff --git a/packages/asset-swapper/src/utils/utils.ts b/packages/asset-swapper/src/utils/utils.ts
index 5c2907be1b..14e12fb203 100644
--- a/packages/asset-swapper/src/utils/utils.ts
+++ b/packages/asset-swapper/src/utils/utils.ts
@@ -1,11 +1,11 @@
-import { SignedOrder } from '@0x/types';
+import { Order } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { AbiDefinition, ContractAbi, MethodAbi } from 'ethereum-types';
import * as _ from 'lodash';
import { constants } from '../constants';
-import { OrdersAndFillableAmounts } from '../types';
+import { PrunedSignedOrder } from '../types';
// tslint:disable:no-unnecessary-type-assertion
export const utils = {
@@ -27,15 +27,30 @@ export const utils = {
},
) as MethodAbi | undefined;
},
- isFeeOrdersRequiredToFillOrders(ordersAndFillableAmounts: OrdersAndFillableAmounts): boolean {
- const { orders, remainingFillableMakerAssetAmounts } = ordersAndFillableAmounts;
- return _.some(
- orders,
- (order: SignedOrder, index: number): boolean => {
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- // If takerFee is a non zero value and order is still fillable, fee orders are required
- return !order.takerFee.isZero() && !remainingFillableMakerAssetAmount.isZero();
- },
- );
+ isOrderTakerFeePayableWithMakerAsset(order: T): boolean {
+ return order.takerFeeAssetData === order.makerAssetData;
+ },
+ isOrderTakerFeePayableWithTakerAsset(order: T): boolean {
+ return order.takerFeeAssetData === order.takerAssetData;
+ },
+ getAdjustedMakerAndTakerAmountsFromTakerFees(order: T): [BigNumber, BigNumber] {
+ const adjustedMakerAssetAmount = utils.isOrderTakerFeePayableWithMakerAsset(order)
+ ? order.makerAssetAmount.minus(order.takerFee)
+ : order.makerAssetAmount;
+ const adjustedTakerAssetAmount = utils.isOrderTakerFeePayableWithTakerAsset(order)
+ ? order.takerAssetAmount.plus(order.takerFee)
+ : order.takerAssetAmount;
+ return [adjustedMakerAssetAmount, adjustedTakerAssetAmount];
+ },
+ getAdjustedFillableMakerAndTakerAmountsFromTakerFees(
+ order: T,
+ ): [BigNumber, BigNumber] {
+ const adjustedFillableMakerAssetAmount = utils.isOrderTakerFeePayableWithMakerAsset(order)
+ ? order.fillableMakerAssetAmount.minus(order.fillableTakerFeeAmount)
+ : order.fillableMakerAssetAmount;
+ const adjustedFillableTakerAssetAmount = utils.isOrderTakerFeePayableWithTakerAsset(order)
+ ? order.fillableTakerAssetAmount.plus(order.fillableTakerFeeAmount)
+ : order.fillableTakerAssetAmount;
+ return [adjustedFillableMakerAssetAmount, adjustedFillableTakerAssetAmount];
},
};
diff --git a/packages/asset-swapper/test/affiliate_fee_utils_test.ts b/packages/asset-swapper/test/affiliate_fee_utils_test.ts
deleted file mode 100644
index a321eb95a6..0000000000
--- a/packages/asset-swapper/test/affiliate_fee_utils_test.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import { MarketOperation } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import * as chai from 'chai';
-import 'mocha';
-
-import { constants } from '../src/constants';
-import { affiliateFeeUtils } from '../src/utils/affiliate_fee_utils';
-
-import { chaiSetup } from './utils/chai_setup';
-import {
- getFullyFillableSwapQuoteWithFees,
- getFullyFillableSwapQuoteWithNoFees,
- getPartialSignedOrdersWithFees,
- getPartialSignedOrdersWithNoFees,
-} from './utils/swap_quote';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-const FAKE_TAKER_ASSET_DATA = '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48';
-const FAKE_MAKER_ASSET_DATA = '0xf47261b00000000000000000000000009f5B0C7e1623793bF0620569b9749e79DF6D0bC5';
-const NULL_ADDRESS = constants.NULL_ADDRESS;
-const FEE_PERCENTAGE = 0.1;
-const FILLABLE_AMOUNTS = [new BigNumber(2), new BigNumber(3), new BigNumber(5)];
-const FILLABLE_FEE_AMOUNTS = [new BigNumber(1), new BigNumber(1), new BigNumber(1)];
-const MARKET_OPERATION = MarketOperation.Sell;
-
-describe('affiliateFeeUtils', () => {
- const fakeFeeOrders = getPartialSignedOrdersWithNoFees(
- FAKE_MAKER_ASSET_DATA,
- FAKE_TAKER_ASSET_DATA,
- NULL_ADDRESS,
- NULL_ADDRESS,
- FILLABLE_FEE_AMOUNTS,
- );
- const fakeOrders = getPartialSignedOrdersWithNoFees(
- FAKE_MAKER_ASSET_DATA,
- FAKE_TAKER_ASSET_DATA,
- NULL_ADDRESS,
- NULL_ADDRESS,
- FILLABLE_AMOUNTS,
- );
-
- const fakeOrdersWithFees = getPartialSignedOrdersWithFees(
- FAKE_MAKER_ASSET_DATA,
- FAKE_TAKER_ASSET_DATA,
- NULL_ADDRESS,
- NULL_ADDRESS,
- FILLABLE_AMOUNTS,
- FILLABLE_FEE_AMOUNTS,
- );
-
- const fakeSwapQuote = getFullyFillableSwapQuoteWithNoFees(
- FAKE_MAKER_ASSET_DATA,
- FAKE_TAKER_ASSET_DATA,
- fakeOrders,
- MARKET_OPERATION,
- );
-
- const fakeSwapQuoteWithFees = getFullyFillableSwapQuoteWithFees(
- FAKE_MAKER_ASSET_DATA,
- FAKE_TAKER_ASSET_DATA,
- fakeOrdersWithFees,
- fakeFeeOrders,
- MARKET_OPERATION,
- );
-
- describe('getSwapQuoteWithAffiliateFee', () => {
- it('should return unchanged swapQuote if feePercentage is 0', () => {
- const updatedSwapQuote = affiliateFeeUtils.getSwapQuoteWithAffiliateFee(fakeSwapQuote, 0);
- const fakeSwapQuoteWithAffiliateFees = { ...fakeSwapQuote, ...{ feePercentage: 0 } };
- expect(updatedSwapQuote).to.deep.equal(fakeSwapQuoteWithAffiliateFees);
- });
- it('should return correct feeTakerToken and totalTakerToken amounts when provided SwapQuote with no fees', () => {
- const updatedSwapQuote = affiliateFeeUtils.getSwapQuoteWithAffiliateFee(fakeSwapQuote, FEE_PERCENTAGE);
- expect(updatedSwapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.deep.equal(new BigNumber(1));
- expect(updatedSwapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.deep.equal(new BigNumber(11));
- expect(updatedSwapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.deep.equal(new BigNumber(1));
- expect(updatedSwapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.deep.equal(new BigNumber(11));
- });
- it('should return correct feeTakerToken and totalTakerToken amounts when provides SwapQuote with fees', () => {
- const updatedSwapQuote = affiliateFeeUtils.getSwapQuoteWithAffiliateFee(
- fakeSwapQuoteWithFees,
- FEE_PERCENTAGE,
- );
- expect(updatedSwapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.deep.equal(new BigNumber(4));
- expect(updatedSwapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.deep.equal(new BigNumber(14));
- expect(updatedSwapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.deep.equal(new BigNumber(4));
- expect(updatedSwapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.deep.equal(new BigNumber(14));
- });
- });
-});
diff --git a/packages/asset-swapper/test/calculate_liquidity_test.ts b/packages/asset-swapper/test/calculate_liquidity_test.ts
new file mode 100644
index 0000000000..0c7c499e3e
--- /dev/null
+++ b/packages/asset-swapper/test/calculate_liquidity_test.ts
@@ -0,0 +1,57 @@
+import * as chai from 'chai';
+import * as _ from 'lodash';
+import 'mocha';
+
+import { calculateLiquidity } from '../src/utils/calculate_liquidity';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrders } from './utils/test_orders';
+import { baseUnitAmount } from './utils/utils';
+
+chaiSetup.configure();
+const expect = chai.expect;
+const {
+ PRUNED_SIGNED_ORDERS_FEELESS,
+ PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+} = testOrders;
+
+// tslint:disable:custom-no-magic-numbers
+describe('#calculateLiquidity', () => {
+ it('should provide correct liquidity result with feeless orders', () => {
+ const prunedSignedOrders = PRUNED_SIGNED_ORDERS_FEELESS;
+ const { makerAssetAvailableInBaseUnits, takerAssetAvailableInBaseUnits } = calculateLiquidity(
+ prunedSignedOrders,
+ );
+ expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(10));
+ expect(takerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(9));
+ });
+ it('should provide correct liquidity result with orders with takerFees in takerAsset', () => {
+ const prunedSignedOrders = PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET;
+ const { makerAssetAvailableInBaseUnits, takerAssetAvailableInBaseUnits } = calculateLiquidity(
+ prunedSignedOrders,
+ );
+ expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(10));
+ expect(takerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(15));
+ });
+ it('should provide correct liquidity result with orders with takerFees in makerAsset', () => {
+ const prunedSignedOrders = PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET;
+ const { makerAssetAvailableInBaseUnits, takerAssetAvailableInBaseUnits } = calculateLiquidity(
+ prunedSignedOrders,
+ );
+ expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(5));
+ expect(takerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(9));
+ });
+ it('should provide correct liquidity result with mixed orders with fees and no fees', () => {
+ const prunedSignedOrders = _.concat(
+ PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ PRUNED_SIGNED_ORDERS_FEELESS,
+ );
+ const { makerAssetAvailableInBaseUnits, takerAssetAvailableInBaseUnits } = calculateLiquidity(
+ prunedSignedOrders,
+ );
+ expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(25));
+ expect(takerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(33));
+ });
+});
diff --git a/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts b/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts
index 880435e249..87b74bd36d 100644
--- a/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts
+++ b/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts
@@ -1,7 +1,9 @@
-import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers';
+import { ContractAddresses } from '@0x/contract-addresses';
+import { DevUtilsContract } from '@0x/contracts-dev-utils';
+import { ERC20TokenContract } from '@0x/contracts-erc20';
+import { ExchangeContract } from '@0x/contracts-exchange';
import { constants as devConstants, OrderFactory } from '@0x/contracts-test-utils';
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
-import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
@@ -13,7 +15,9 @@ import {
ExchangeMarketBuySmartContractParams,
ExchangeMarketSellSmartContractParams,
MarketBuySwapQuote,
+ MarketOperation,
MarketSellSwapQuote,
+ PrunedSignedOrder,
} from '../src/types';
import { chaiSetup } from './utils/chai_setup';
@@ -25,16 +29,47 @@ chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+const GAS_PRICE = new BigNumber(devConstants.DEFAULT_GAS_PRICE);
const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000);
-const TESTRPC_CHAIN_ID = 1337;
-const FILLABLE_AMOUNTS = [new BigNumber(3), new BigNumber(2), new BigNumber(5)].map(value =>
- value.multipliedBy(ONE_ETH_IN_WEI),
-);
+const TESTRPC_CHAIN_ID = devConstants.TESTRPC_CHAIN_ID;
+const UNLIMITED_ALLOWANCE = new BigNumber(2).pow(256).minus(1); // tslint:disable-line:custom-no-magic-numbers
+
+const PARTIAL_PRUNED_SIGNED_ORDERS_FEELESS: Array> = [
+ {
+ takerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ },
+ {
+ takerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ },
+ {
+ takerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ },
+];
+
+const expectMakerAndTakerBalancesAsyncFactory = (
+ erc20TokenContract: ERC20TokenContract,
+ makerAddress: string,
+ takerAddress: string,
+) => async (expectedMakerBalance: BigNumber, expectedTakerBalance: BigNumber) => {
+ const makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
+ const takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
+ expect(makerBalance).to.bignumber.equal(expectedMakerBalance);
+ expect(takerBalance).to.bignumber.equal(expectedTakerBalance);
+};
describe('ExchangeSwapQuoteConsumer', () => {
- let contractWrappers: ContractWrappers;
let userAddresses: string[];
- let erc20TokenContract: ERC20TokenContract;
+ let erc20MakerTokenContract: ERC20TokenContract;
+ let erc20TakerTokenContract: ERC20TokenContract;
let coinbaseAddress: string;
let makerAddress: string;
let takerAddress: string;
@@ -46,32 +81,38 @@ describe('ExchangeSwapQuoteConsumer', () => {
let takerAssetData: string;
let wethAssetData: string;
let contractAddresses: ContractAddresses;
+ let exchangeContract: ExchangeContract;
const chainId = TESTRPC_CHAIN_ID;
- let orders: SignedOrder[];
+ let orders: PrunedSignedOrder[];
let marketSellSwapQuote: SwapQuote;
let marketBuySwapQuote: SwapQuote;
let swapQuoteConsumer: ExchangeSwapQuoteConsumer;
+ let expectMakerAndTakerBalancesForMakerAssetAsync: (
+ expectedMakerBalance: BigNumber,
+ expectedTakerBalance: BigNumber,
+ ) => Promise;
+ let expectMakerAndTakerBalancesForTakerAssetAsync: (
+ expectedMakerBalance: BigNumber,
+ expectedTakerBalance: BigNumber,
+ ) => Promise;
before(async () => {
contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
- const config = {
- chainId,
- contractAddresses,
- };
- contractWrappers = new ContractWrappers(provider, config);
[coinbaseAddress, takerAddress, makerAddress, feeRecipient] = userAddresses;
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
- [makerAssetData, takerAssetData, wethAssetData] = [
- await contractWrappers.devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
- await contractWrappers.devUtils.encodeERC20AssetData(takerTokenAddress).callAsync(),
- await contractWrappers.devUtils.encodeERC20AssetData(contractAddresses.etherToken).callAsync(),
- ];
- erc20TokenContract = new ERC20TokenContract(makerTokenAddress, provider);
-
+ const devUtils = new DevUtilsContract(contractAddresses.devUtils, provider);
+ [makerAssetData, takerAssetData, wethAssetData] = await Promise.all([
+ devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
+ devUtils.encodeERC20AssetData(takerTokenAddress).callAsync(),
+ devUtils.encodeERC20AssetData(contractAddresses.etherToken).callAsync(),
+ ]);
+ erc20MakerTokenContract = new ERC20TokenContract(makerTokenAddress, provider);
+ erc20TakerTokenContract = new ERC20TokenContract(takerTokenAddress, provider);
+ exchangeContract = new ExchangeContract(contractAddresses.exchange, provider);
// Configure order defaults
const defaultOrderParams = {
...devConstants.STATIC_ORDER_PARAMS,
@@ -79,17 +120,26 @@ describe('ExchangeSwapQuoteConsumer', () => {
takerAddress,
makerAssetData,
takerAssetData,
- makerFeeAssetData: await contractWrappers.devUtils
- .encodeERC20AssetData(contractAddresses.zrxToken)
- .callAsync(),
- takerFeeAssetData: await contractWrappers.devUtils
- .encodeERC20AssetData(contractAddresses.zrxToken)
- .callAsync(),
+ makerFeeAssetData: constants.NULL_ERC20_ASSET_DATA,
+ takerFeeAssetData: constants.NULL_ERC20_ASSET_DATA,
+ makerFee: constants.ZERO_AMOUNT,
+ takerFee: constants.ZERO_AMOUNT,
+ feeRecipientAddress: feeRecipient,
exchangeAddress: contractAddresses.exchange,
chainId,
};
const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
+ expectMakerAndTakerBalancesForTakerAssetAsync = expectMakerAndTakerBalancesAsyncFactory(
+ erc20TakerTokenContract,
+ makerAddress,
+ takerAddress,
+ );
+ expectMakerAndTakerBalancesForMakerAssetAsync = expectMakerAndTakerBalancesAsyncFactory(
+ erc20MakerTokenContract,
+ makerAddress,
+ takerAddress,
+ );
});
after(async () => {
await blockchainLifecycle.revertAsync();
@@ -97,12 +147,13 @@ describe('ExchangeSwapQuoteConsumer', () => {
beforeEach(async () => {
await blockchainLifecycle.startAsync();
orders = [];
- for (const fillableAmount of FILLABLE_AMOUNTS) {
- const order = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: fillableAmount,
- takerAssetAmount: fillableAmount,
- });
- orders.push(order);
+ for (const partialOrder of PARTIAL_PRUNED_SIGNED_ORDERS_FEELESS) {
+ const order = await orderFactory.newSignedOrderAsync(partialOrder);
+ const prunedOrder = {
+ ...order,
+ ...partialOrder,
+ };
+ orders.push(prunedOrder as PrunedSignedOrder);
}
marketSellSwapQuote = getFullyFillableSwapQuoteWithNoFees(
@@ -110,6 +161,7 @@ describe('ExchangeSwapQuoteConsumer', () => {
takerAssetData,
orders,
MarketOperation.Sell,
+ GAS_PRICE,
);
marketBuySwapQuote = getFullyFillableSwapQuoteWithNoFees(
@@ -117,45 +169,87 @@ describe('ExchangeSwapQuoteConsumer', () => {
takerAssetData,
orders,
MarketOperation.Buy,
+ GAS_PRICE,
);
- swapQuoteConsumer = new ExchangeSwapQuoteConsumer(provider, {
+ swapQuoteConsumer = new ExchangeSwapQuoteConsumer(provider, contractAddresses, {
chainId,
});
+
+ await erc20MakerTokenContract
+ .transfer(makerAddress, marketBuySwapQuote.worstCaseQuoteInfo.makerAssetAmount)
+ .sendTransactionAsync({
+ from: coinbaseAddress,
+ });
+ await erc20TakerTokenContract
+ .transfer(takerAddress, marketBuySwapQuote.worstCaseQuoteInfo.totalTakerAssetAmount)
+ .sendTransactionAsync({
+ from: coinbaseAddress,
+ });
+ await erc20MakerTokenContract
+ .approve(contractAddresses.erc20Proxy, UNLIMITED_ALLOWANCE)
+ .sendTransactionAsync({ from: makerAddress });
+ await erc20TakerTokenContract
+ .approve(contractAddresses.erc20Proxy, UNLIMITED_ALLOWANCE)
+ .sendTransactionAsync({ from: takerAddress });
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
- describe('executeSwapQuoteOrThrowAsync', () => {
+ describe('#executeSwapQuoteOrThrowAsync', () => {
/*
* Testing that SwapQuoteConsumer logic correctly performs a execution (doesn't throw or revert)
* Does not test the validity of the state change performed by the forwarder smart contract
*/
it('should perform a marketSell execution when provided a MarketSell type swapQuote', async () => {
- let makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, { takerAddress });
- makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
+ await expectMakerAndTakerBalancesForMakerAssetAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ await expectMakerAndTakerBalancesForTakerAssetAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, {
+ takerAddress,
+ gasPrice: GAS_PRICE,
+ gasLimit: 4000000,
+ });
+ await expectMakerAndTakerBalancesForMakerAssetAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ await expectMakerAndTakerBalancesForTakerAssetAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
});
it('should perform a marketBuy execution when provided a MarketBuy type swapQuote', async () => {
- let makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, { takerAddress });
- makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
+ await expectMakerAndTakerBalancesForMakerAssetAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ await expectMakerAndTakerBalancesForTakerAssetAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, {
+ takerAddress,
+ gasPrice: GAS_PRICE,
+ gasLimit: 4000000,
+ });
+ await expectMakerAndTakerBalancesForMakerAssetAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ await expectMakerAndTakerBalancesForTakerAssetAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
});
});
- describe('getSmartContractParamsOrThrow', () => {
+ describe('#getSmartContractParamsOrThrow', () => {
describe('valid swap quote', async () => {
// TODO(david) Check for valid MethodAbi
it('provide correct and optimized smart contract params for a marketSell SwapQuote', async () => {
@@ -163,7 +257,7 @@ describe('ExchangeSwapQuoteConsumer', () => {
marketSellSwapQuote,
{},
);
- expect(toAddress).to.deep.equal(contractWrappers.exchange.address);
+ expect(toAddress).to.deep.equal(exchangeContract.address);
const { takerAssetFillAmount, signatures, type } = params as ExchangeMarketSellSmartContractParams;
expect(type).to.deep.equal(MarketOperation.Sell);
expect(takerAssetFillAmount).to.bignumber.equal(
@@ -172,12 +266,12 @@ describe('ExchangeSwapQuoteConsumer', () => {
const orderSignatures = marketSellSwapQuote.orders.map(order => order.signature);
expect(signatures).to.deep.equal(orderSignatures);
});
- it('provide correct and optimized smart contract params for a marketBuy SwapQuote', async () => {
+ it('provide correct smart contract params for a marketBuy SwapQuote', async () => {
const { toAddress, params } = await swapQuoteConsumer.getSmartContractParamsOrThrowAsync(
marketBuySwapQuote,
{},
);
- expect(toAddress).to.deep.equal(contractWrappers.exchange.address);
+ expect(toAddress).to.deep.equal(exchangeContract.address);
const { makerAssetFillAmount, signatures, type } = params as ExchangeMarketBuySmartContractParams;
expect(type).to.deep.equal(MarketOperation.Buy);
expect(makerAssetFillAmount).to.bignumber.equal(
@@ -189,49 +283,53 @@ describe('ExchangeSwapQuoteConsumer', () => {
});
});
- describe('getCalldataOrThrow', () => {
+ describe('#getCalldataOrThrow', () => {
describe('valid swap quote', async () => {
it('provide correct and optimized calldata options with default options for a marketSell SwapQuote (no affiliate fees)', async () => {
- let makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- const { calldataHexString, toAddress } = await swapQuoteConsumer.getCalldataOrThrowAsync(
+ await expectMakerAndTakerBalancesForMakerAssetAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ const { calldataHexString, toAddress, ethAmount } = await swapQuoteConsumer.getCalldataOrThrowAsync(
marketSellSwapQuote,
{},
);
- expect(toAddress).to.deep.equal(contractWrappers.exchange.address);
+ expect(toAddress).to.deep.equal(exchangeContract.address);
await web3Wrapper.sendTransactionAsync({
from: takerAddress,
to: toAddress,
data: calldataHexString,
gas: 4000000,
+ gasPrice: GAS_PRICE,
+ value: ethAmount,
});
- makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
+ await expectMakerAndTakerBalancesForMakerAssetAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
});
it('provide correct and optimized calldata options with default options for a marketBuy SwapQuote (no affiliate fees)', async () => {
- let makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- const { calldataHexString, toAddress } = await swapQuoteConsumer.getCalldataOrThrowAsync(
+ await expectMakerAndTakerBalancesForMakerAssetAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ const { calldataHexString, toAddress, ethAmount } = await swapQuoteConsumer.getCalldataOrThrowAsync(
marketBuySwapQuote,
{},
);
- expect(toAddress).to.deep.equal(contractWrappers.exchange.address);
+ expect(toAddress).to.deep.equal(exchangeContract.address);
await web3Wrapper.sendTransactionAsync({
from: takerAddress,
to: toAddress,
data: calldataHexString,
gas: 4000000,
+ gasPrice: GAS_PRICE,
+ value: ethAmount,
});
- makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
+ await expectMakerAndTakerBalancesForMakerAssetAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
});
});
});
diff --git a/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts b/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts
index 2cdbd90386..d9f5343a62 100644
--- a/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts
+++ b/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts
@@ -1,6 +1,9 @@
-import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers';
+import { ContractAddresses } from '@0x/contract-addresses';
+import { DevUtilsContract } from '@0x/contracts-dev-utils';
+import { ERC20TokenContract } from '@0x/contracts-erc20';
+import { ForwarderContract } from '@0x/contracts-exchange-forwarder';
+import { constants as devConstants, OrderFactory } from '@0x/contracts-test-utils';
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
-import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
@@ -12,28 +15,61 @@ import {
ForwarderMarketBuySmartContractParams,
ForwarderMarketSellSmartContractParams,
MarketBuySwapQuote,
+ MarketOperation,
+ PrunedSignedOrder,
} from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { migrateOnceAsync } from './utils/migrate';
-import { getFullyFillableSwapQuoteWithNoFees, getSignedOrdersWithNoFeesAsync } from './utils/swap_quote';
+import { getFullyFillableSwapQuoteWithNoFees } from './utils/swap_quote';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+const GAS_PRICE = new BigNumber(devConstants.DEFAULT_GAS_PRICE);
const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000);
-const TESTRPC_CHAIN_ID = 1337;
-const MARKET_OPERATION = MarketOperation.Sell;
+const TESTRPC_CHAIN_ID = devConstants.TESTRPC_CHAIN_ID;
const FILLABLE_AMOUNTS = [new BigNumber(2), new BigNumber(3), new BigNumber(5)].map(value =>
value.multipliedBy(ONE_ETH_IN_WEI),
);
const UNLIMITED_ALLOWANCE_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1); // tslint:disable-line:custom-no-magic-numbers
+const PARTIAL_PRUNED_SIGNED_ORDERS_FEELESS: Array> = [
+ {
+ takerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ },
+ {
+ takerAssetAmount: new BigNumber(1).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(1).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ },
+ {
+ takerAssetAmount: new BigNumber(1).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(1).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ },
+];
+
+const expectMakerAndTakerBalancesAsyncFactory = (
+ erc20TokenContract: ERC20TokenContract,
+ makerAddress: string,
+ takerAddress: string,
+) => async (expectedMakerBalance: BigNumber, expectedTakerBalance: BigNumber) => {
+ const makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
+ const takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
+ expect(makerBalance).to.bignumber.equal(expectedMakerBalance);
+ expect(takerBalance).to.bignumber.equal(expectedTakerBalance);
+};
+
describe('ForwarderSwapQuoteConsumer', () => {
- let contractWrappers: ContractWrappers;
- let erc20Token: ERC20TokenContract;
+ const FEE_PERCENTAGE = 0.05;
let userAddresses: string[];
let coinbaseAddress: string;
let makerAddress: string;
@@ -43,33 +79,68 @@ describe('ForwarderSwapQuoteConsumer', () => {
let takerTokenAddress: string;
let makerAssetData: string;
let takerAssetData: string;
+ let orderFactory: OrderFactory;
+ let invalidOrderFactory: OrderFactory;
let wethAssetData: string;
let contractAddresses: ContractAddresses;
+ let erc20TokenContract: ERC20TokenContract;
+ let forwarderContract: ForwarderContract;
- let orders: SignedOrder[];
+ let orders: PrunedSignedOrder[];
+ let invalidOrders: PrunedSignedOrder[];
let marketSellSwapQuote: SwapQuote;
let marketBuySwapQuote: SwapQuote;
+ let invalidMarketBuySwapQuote: SwapQuote;
let swapQuoteConsumer: ForwarderSwapQuoteConsumer;
- let erc20ProxyAddress: string;
-
+ let expectMakerAndTakerBalancesAsync: (
+ expectedMakerBalance: BigNumber,
+ expectedTakerBalance: BigNumber,
+ ) => Promise;
const chainId = TESTRPC_CHAIN_ID;
+
before(async () => {
contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
- const config = {
- chainId,
- contractAddresses,
- };
- contractWrappers = new ContractWrappers(provider, config);
[coinbaseAddress, takerAddress, makerAddress, feeRecipient] = userAddresses;
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
- erc20Token = new ERC20TokenContract(makerTokenAddress, provider);
- [makerAssetData, takerAssetData, wethAssetData] = [
- await contractWrappers.devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
- await contractWrappers.devUtils.encodeERC20AssetData(takerTokenAddress).callAsync(),
- await contractWrappers.devUtils.encodeERC20AssetData(contractAddresses.etherToken).callAsync(),
- ];
+ erc20TokenContract = new ERC20TokenContract(makerTokenAddress, provider);
+ forwarderContract = new ForwarderContract(contractAddresses.forwarder, provider);
+ const devUtils = new DevUtilsContract(contractAddresses.devUtils, provider);
+ [makerAssetData, takerAssetData, wethAssetData] = await Promise.all([
+ devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
+ devUtils.encodeERC20AssetData(takerTokenAddress).callAsync(),
+ devUtils.encodeERC20AssetData(contractAddresses.etherToken).callAsync(),
+ ]);
+ // Configure order defaults
+ const defaultOrderParams = {
+ ...devConstants.STATIC_ORDER_PARAMS,
+ makerAddress,
+ takerAddress: constants.NULL_ADDRESS,
+ makerAssetData,
+ takerAssetData: wethAssetData,
+ makerFeeAssetData: constants.NULL_ERC20_ASSET_DATA,
+ takerFeeAssetData: constants.NULL_ERC20_ASSET_DATA,
+ makerFee: constants.ZERO_AMOUNT,
+ takerFee: constants.ZERO_AMOUNT,
+ feeRecipientAddress: feeRecipient,
+ exchangeAddress: contractAddresses.exchange,
+ chainId,
+ };
+ const invalidDefaultOrderParams = {
+ ...defaultOrderParams,
+ ...{
+ takerAssetData,
+ },
+ };
+ const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
+ orderFactory = new OrderFactory(privateKey, defaultOrderParams);
+ expectMakerAndTakerBalancesAsync = expectMakerAndTakerBalancesAsyncFactory(
+ erc20TokenContract,
+ makerAddress,
+ takerAddress,
+ );
+ invalidOrderFactory = new OrderFactory(privateKey, invalidDefaultOrderParams);
});
after(async () => {
await blockchainLifecycle.revertAsync();
@@ -77,35 +148,48 @@ describe('ForwarderSwapQuoteConsumer', () => {
beforeEach(async () => {
await blockchainLifecycle.startAsync();
const UNLIMITED_ALLOWANCE = UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
- erc20ProxyAddress = contractAddresses.erc20Proxy;
const totalFillableAmount = FILLABLE_AMOUNTS.reduce(
(a: BigNumber, c: BigNumber) => a.plus(c),
new BigNumber(0),
);
- await erc20Token.transfer(makerAddress, totalFillableAmount).sendTransactionAsync({
+ await erc20TokenContract.transfer(makerAddress, totalFillableAmount).sendTransactionAsync({
from: coinbaseAddress,
});
- await erc20Token.approve(erc20ProxyAddress, UNLIMITED_ALLOWANCE).sendTransactionAsync({
- from: makerAddress,
- });
- orders = await getSignedOrdersWithNoFeesAsync(
- provider,
- makerAssetData,
- wethAssetData,
- makerAddress,
- takerAddress,
- FILLABLE_AMOUNTS,
- contractAddresses.exchange,
- );
+ await erc20TokenContract
+ .approve(contractAddresses.erc20Proxy, UNLIMITED_ALLOWANCE)
+ .sendTransactionAsync({ from: makerAddress });
+
+ await forwarderContract.approveMakerAssetProxy(makerAssetData).sendTransactionAsync({ from: makerAddress });
+
+ orders = [];
+ for (const partialOrder of PARTIAL_PRUNED_SIGNED_ORDERS_FEELESS) {
+ const order = await orderFactory.newSignedOrderAsync(partialOrder);
+ const prunedOrder = {
+ ...order,
+ ...partialOrder,
+ };
+ orders.push(prunedOrder as PrunedSignedOrder);
+ }
+
+ invalidOrders = [];
+ for (const partialOrder of PARTIAL_PRUNED_SIGNED_ORDERS_FEELESS) {
+ const order = await invalidOrderFactory.newSignedOrderAsync(partialOrder);
+ const prunedOrder = {
+ ...order,
+ ...partialOrder,
+ };
+ invalidOrders.push(prunedOrder as PrunedSignedOrder);
+ }
marketSellSwapQuote = getFullyFillableSwapQuoteWithNoFees(
makerAssetData,
wethAssetData,
orders,
MarketOperation.Sell,
+ GAS_PRICE,
);
marketBuySwapQuote = getFullyFillableSwapQuoteWithNoFees(
@@ -113,34 +197,29 @@ describe('ForwarderSwapQuoteConsumer', () => {
wethAssetData,
orders,
MarketOperation.Buy,
+ GAS_PRICE,
);
- swapQuoteConsumer = new ForwarderSwapQuoteConsumer(provider, {
+ invalidMarketBuySwapQuote = getFullyFillableSwapQuoteWithNoFees(
+ makerAssetData,
+ takerAssetData,
+ invalidOrders,
+ MarketOperation.Buy,
+ GAS_PRICE,
+ );
+
+ swapQuoteConsumer = new ForwarderSwapQuoteConsumer(provider, contractAddresses, {
chainId,
});
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
- describe('executeSwapQuoteOrThrowAsync', () => {
+ describe('#executeSwapQuoteOrThrowAsync', () => {
describe('validation', () => {
- it('should throw if swapQuote provided is not a valid forwarder SwapQuote (taker asset is wEth', async () => {
- const invalidSignedOrders = await getSignedOrdersWithNoFeesAsync(
- provider,
- makerAssetData,
- takerAssetData,
- makerAddress,
- takerAddress,
- FILLABLE_AMOUNTS,
- );
- const invalidSwapQuote = getFullyFillableSwapQuoteWithNoFees(
- makerAssetData,
- takerAssetData,
- invalidSignedOrders,
- MARKET_OPERATION,
- );
+ it('should throw if swapQuote provided is not a valid forwarder SwapQuote (taker asset is wEth)', async () => {
expect(
- swapQuoteConsumer.executeSwapQuoteOrThrowAsync(invalidSwapQuote, { takerAddress }),
+ swapQuoteConsumer.executeSwapQuoteOrThrowAsync(invalidMarketBuySwapQuote, { takerAddress }),
).to.be.rejectedWith(
`Expected quote.orders[0] to have takerAssetData set as ${wethAssetData}, but is ${takerAssetData}`,
);
@@ -153,89 +232,98 @@ describe('ForwarderSwapQuoteConsumer', () => {
* Testing that SwapQuoteConsumer logic correctly performs a execution (doesn't throw or revert)
* Does not test the validity of the state change performed by the forwarder smart contract
*/
- it('should perform a marketSell execution when provided a MarketSell type swapQuote', async () => {
- let makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, { takerAddress });
- makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(0.5).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(new BigNumber(9.5).multipliedBy(ONE_ETH_IN_WEI));
+ it('should perform a marketBuy execution when provided a MarketBuy type swapQuote', async () => {
+ await expectMakerAndTakerBalancesAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, {
+ takerAddress,
+ gasPrice: GAS_PRICE,
+ gasLimit: 4000000,
+ });
+ await expectMakerAndTakerBalancesAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
});
- it('should perform a marketBuy execution when provided a MarketBuy type swapQuote', async () => {
- let makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, { takerAddress });
- makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
+ it('should perform a marketSell execution when provided a MarketSell type swapQuote', async () => {
+ await expectMakerAndTakerBalancesAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, {
+ takerAddress,
+ gasPrice: GAS_PRICE,
+ gasLimit: 4000000,
+ });
+ await expectMakerAndTakerBalancesAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
});
it('should perform a marketBuy execution with affiliate fees', async () => {
- let makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
+ await expectMakerAndTakerBalancesAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, {
takerAddress,
- feePercentage: 0.05,
+ gasPrice: GAS_PRICE,
+ gasLimit: 4000000,
+ feePercentage: FEE_PERCENTAGE,
feeRecipient,
});
- makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
+ await expectMakerAndTakerBalancesAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
- expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
+ const totalEthSpent = marketBuySwapQuote.bestCaseQuoteInfo.totalTakerAssetAmount.plus(
+ marketBuySwapQuote.bestCaseQuoteInfo.protocolFeeInEthAmount,
+ );
expect(feeRecipientEthBalanceAfter.minus(feeRecipientEthBalanceBefore)).to.bignumber.equal(
- new BigNumber(0.5).multipliedBy(ONE_ETH_IN_WEI),
+ new BigNumber(FEE_PERCENTAGE).times(totalEthSpent),
);
});
- // TODO(david) Finish marketSell affiliate fee excution testing
- // it('should perform a marketSell execution with affiliate fees', async () => {
- // let makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- // let takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- // const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
- // expect(makerBalance).to.bignumber.equal((new BigNumber(10)).multipliedBy(ONE_ETH_IN_WEI));
- // expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- // console.log(makerBalance, takerBalance, feeRecipientEthBalanceBefore);
- // await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, { takerAddress, feePercentage: 0.05, feeRecipient });
- // makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- // takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- // const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
- // console.log(makerBalance, takerBalance, feeRecipientEthBalanceAfter);
- // expect(makerBalance).to.bignumber.equal((new BigNumber(0.5)).multipliedBy(ONE_ETH_IN_WEI));
- // expect(takerBalance).to.bignumber.equal((new BigNumber(9.5)).multipliedBy(ONE_ETH_IN_WEI));
- // expect(feeRecipientEthBalanceAfter.minus(feeRecipientEthBalanceBefore)).to.bignumber.equal((new BigNumber(0.5)).multipliedBy(ONE_ETH_IN_WEI));
- // });
+ it('should perform a marketSell execution with affiliate fees', async () => {
+ await expectMakerAndTakerBalancesAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
+ await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, {
+ takerAddress,
+ feePercentage: FEE_PERCENTAGE,
+ feeRecipient,
+ gasPrice: GAS_PRICE,
+ gasLimit: 4000000,
+ });
+ await expectMakerAndTakerBalancesAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
+ const totalEthSpent = marketBuySwapQuote.bestCaseQuoteInfo.totalTakerAssetAmount.plus(
+ marketBuySwapQuote.bestCaseQuoteInfo.protocolFeeInEthAmount,
+ );
+ expect(feeRecipientEthBalanceAfter.minus(feeRecipientEthBalanceBefore)).to.bignumber.equal(
+ new BigNumber(FEE_PERCENTAGE).times(totalEthSpent),
+ );
+ });
});
});
- describe('getSmartContractParamsOrThrow', () => {
+ describe('#getSmartContractParamsOrThrow', () => {
describe('validation', () => {
it('should throw if swap quote provided is not a valid forwarder SwapQuote (taker asset is WETH)', async () => {
- const invalidSignedOrders = await getSignedOrdersWithNoFeesAsync(
- provider,
- makerAssetData,
- takerAssetData,
- makerAddress,
- takerAddress,
- FILLABLE_AMOUNTS,
- );
- const invalidSwapQuote = getFullyFillableSwapQuoteWithNoFees(
- makerAssetData,
- takerAssetData,
- invalidSignedOrders,
- MARKET_OPERATION,
- );
- expect(swapQuoteConsumer.getSmartContractParamsOrThrowAsync(invalidSwapQuote, {})).to.be.rejectedWith(
+ expect(
+ swapQuoteConsumer.getSmartContractParamsOrThrowAsync(invalidMarketBuySwapQuote, {}),
+ ).to.be.rejectedWith(
`Expected quote.orders[0] to have takerAssetData set as ${wethAssetData}, but is ${takerAssetData}`,
);
});
@@ -247,9 +335,8 @@ describe('ForwarderSwapQuoteConsumer', () => {
marketSellSwapQuote,
{},
);
- expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
+ expect(toAddress).to.deep.equal(forwarderContract.address);
const {
- feeSignatures,
feePercentage,
feeRecipient: feeRecipientFromParams,
signatures,
@@ -260,17 +347,15 @@ describe('ForwarderSwapQuoteConsumer', () => {
const orderSignatures = marketSellSwapQuote.orders.map(order => order.signature);
expect(signatures).to.deep.equal(orderSignatures);
expect(feePercentage).to.bignumber.equal(0);
- expect(feeSignatures).to.deep.equal([]);
});
it('provide correct and optimized smart contract params with default options for a marketBuy SwapQuote (no affiliate fees)', async () => {
const { toAddress, params } = await swapQuoteConsumer.getSmartContractParamsOrThrowAsync(
marketBuySwapQuote,
{},
);
- expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
+ expect(toAddress).to.deep.equal(forwarderContract.address);
const {
makerAssetFillAmount,
- feeSignatures,
feePercentage,
feeRecipient: feeRecipientFromParams,
signatures,
@@ -284,7 +369,6 @@ describe('ForwarderSwapQuoteConsumer', () => {
const orderSignatures = marketBuySwapQuote.orders.map(order => order.signature);
expect(signatures).to.deep.equal(orderSignatures);
expect(feePercentage).to.bignumber.equal(0);
- expect(feeSignatures).to.deep.equal([]);
});
it('provide correct and optimized smart contract params with affiliate fees for a marketSell SwapQuote', async () => {
const { toAddress, params } = await swapQuoteConsumer.getSmartContractParamsOrThrowAsync(
@@ -294,9 +378,8 @@ describe('ForwarderSwapQuoteConsumer', () => {
feeRecipient,
},
);
- expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
+ expect(toAddress).to.deep.equal(forwarderContract.address);
const {
- feeSignatures,
feePercentage,
feeRecipient: feeRecipientFromParams,
signatures,
@@ -307,7 +390,6 @@ describe('ForwarderSwapQuoteConsumer', () => {
const orderSignatures = marketSellSwapQuote.orders.map(order => order.signature);
expect(signatures).to.deep.equal(orderSignatures);
expect(feePercentage).to.bignumber.equal(new BigNumber(0.05).multipliedBy(ONE_ETH_IN_WEI));
- expect(feeSignatures).to.deep.equal([]);
});
it('provide correct and optimized smart contract params with affiliate fees for a marketBuy SwapQuote', async () => {
const { toAddress, params } = await swapQuoteConsumer.getSmartContractParamsOrThrowAsync(
@@ -317,10 +399,9 @@ describe('ForwarderSwapQuoteConsumer', () => {
feeRecipient,
},
);
- expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
+ expect(toAddress).to.deep.equal(forwarderContract.address);
const {
makerAssetFillAmount,
- feeSignatures,
feePercentage,
feeRecipient: feeRecipientFromParams,
signatures,
@@ -334,29 +415,14 @@ describe('ForwarderSwapQuoteConsumer', () => {
const orderSignatures = marketBuySwapQuote.orders.map(order => order.signature);
expect(signatures).to.deep.equal(orderSignatures);
expect(feePercentage).to.bignumber.equal(new BigNumber(0.05).multipliedBy(ONE_ETH_IN_WEI));
- expect(feeSignatures).to.deep.equal([]);
});
});
});
- describe('getCalldataOrThrow', () => {
+ describe('#getCalldataOrThrow', () => {
describe('validation', () => {
it('should throw if swap quote provided is not a valid forwarder SwapQuote (taker asset is WETH)', async () => {
- const invalidSignedOrders = await getSignedOrdersWithNoFeesAsync(
- provider,
- makerAssetData,
- takerAssetData,
- makerAddress,
- takerAddress,
- FILLABLE_AMOUNTS,
- );
- const invalidSwapQuote = getFullyFillableSwapQuoteWithNoFees(
- makerAssetData,
- takerAssetData,
- invalidSignedOrders,
- MARKET_OPERATION,
- );
- expect(swapQuoteConsumer.getCalldataOrThrowAsync(invalidSwapQuote, {})).to.be.rejectedWith(
+ expect(swapQuoteConsumer.getCalldataOrThrowAsync(invalidMarketBuySwapQuote, {})).to.be.rejectedWith(
`Expected quote.orders[0] to have takerAssetData set as ${wethAssetData}, but is ${takerAssetData}`,
);
});
@@ -364,33 +430,34 @@ describe('ForwarderSwapQuoteConsumer', () => {
describe('valid swap quote', async () => {
it('provide correct and optimized calldata options with default options for a marketSell SwapQuote (no affiliate fees)', async () => {
- let makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- const { calldataHexString, toAddress } = await swapQuoteConsumer.getCalldataOrThrowAsync(
+ await expectMakerAndTakerBalancesAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ const { calldataHexString, toAddress, ethAmount } = await swapQuoteConsumer.getCalldataOrThrowAsync(
marketSellSwapQuote,
{},
);
- expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
+ expect(toAddress).to.deep.equal(forwarderContract.address);
await web3Wrapper.sendTransactionAsync({
from: takerAddress,
to: toAddress,
data: calldataHexString,
- value: marketSellSwapQuote.worstCaseQuoteInfo.totalTakerTokenAmount,
+ value: ethAmount,
+ gasPrice: GAS_PRICE,
gas: 4000000,
});
- makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(0.5).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(new BigNumber(9.5).multipliedBy(ONE_ETH_IN_WEI));
+ await expectMakerAndTakerBalancesAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
});
it('provide correct and optimized calldata options with default options for a marketBuy SwapQuote (no affiliate fees)', async () => {
- let makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- let takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- const { calldataHexString, toAddress } = await swapQuoteConsumer.getCalldataOrThrowAsync(
+ await expectMakerAndTakerBalancesAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ const { calldataHexString, toAddress, ethAmount } = await swapQuoteConsumer.getCalldataOrThrowAsync(
marketBuySwapQuote,
{},
);
@@ -399,19 +466,84 @@ describe('ForwarderSwapQuoteConsumer', () => {
from: takerAddress,
to: toAddress,
data: calldataHexString,
- value: marketBuySwapQuote.worstCaseQuoteInfo.totalTakerTokenAmount,
+ value: ethAmount,
+ gasPrice: GAS_PRICE,
gas: 4000000,
});
- makerBalance = await erc20Token.balanceOf(makerAddress).callAsync();
- takerBalance = await erc20Token.balanceOf(takerAddress).callAsync();
- expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
+ await expectMakerAndTakerBalancesAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ });
+ it('provide correct and optimized calldata options with affiliate fees for a marketSell SwapQuote', async () => {
+ await expectMakerAndTakerBalancesAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
+ const { calldataHexString, toAddress, ethAmount } = await swapQuoteConsumer.getCalldataOrThrowAsync(
+ marketSellSwapQuote,
+ {
+ feePercentage: FEE_PERCENTAGE,
+ feeRecipient,
+ },
+ );
+ expect(toAddress).to.deep.equal(contractAddresses.forwarder);
+ await web3Wrapper.sendTransactionAsync({
+ from: takerAddress,
+ to: toAddress,
+ data: calldataHexString,
+ value: ethAmount,
+ gasPrice: GAS_PRICE,
+ gas: 4000000,
+ });
+ await expectMakerAndTakerBalancesAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ const totalEthSpent = marketBuySwapQuote.bestCaseQuoteInfo.totalTakerAssetAmount.plus(
+ marketBuySwapQuote.bestCaseQuoteInfo.protocolFeeInEthAmount,
+ );
+ const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
+ expect(feeRecipientEthBalanceAfter.minus(feeRecipientEthBalanceBefore)).to.bignumber.equal(
+ new BigNumber(FEE_PERCENTAGE).times(totalEthSpent),
+ );
+ });
+ it('provide correct and optimized calldata options with affiliate fees for a marketBuy SwapQuote', async () => {
+ await expectMakerAndTakerBalancesAsync(
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ constants.ZERO_AMOUNT,
+ );
+ const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
+ const { calldataHexString, toAddress, ethAmount } = await swapQuoteConsumer.getCalldataOrThrowAsync(
+ marketBuySwapQuote,
+ {
+ feePercentage: FEE_PERCENTAGE,
+ feeRecipient,
+ },
+ );
+ expect(toAddress).to.deep.equal(contractAddresses.forwarder);
+ await web3Wrapper.sendTransactionAsync({
+ from: takerAddress,
+ to: toAddress,
+ data: calldataHexString,
+ value: ethAmount,
+ gasPrice: GAS_PRICE,
+ gas: 4000000,
+ });
+ await expectMakerAndTakerBalancesAsync(
+ constants.ZERO_AMOUNT,
+ new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ const totalEthSpent = marketBuySwapQuote.bestCaseQuoteInfo.totalTakerAssetAmount.plus(
+ marketBuySwapQuote.bestCaseQuoteInfo.protocolFeeInEthAmount,
+ );
+ const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipient);
+ expect(feeRecipientEthBalanceAfter.minus(feeRecipientEthBalanceBefore)).to.bignumber.equal(
+ new BigNumber(FEE_PERCENTAGE).times(totalEthSpent),
+ );
});
- // TODO(david) finish testing for affiliate fees calldata output
- // it('provide correct and optimized calldata options with affiliate fees for a marketSell SwapQuote', async () => {
- // });
- // it('provide correct and optimized calldata options with affiliate fees for a marketBuy SwapQuote', async () => {
- // });
});
});
+ // tslint:disable-next-line: max-file-line-count
});
diff --git a/packages/asset-swapper/test/market_utils_test.ts b/packages/asset-swapper/test/market_utils_test.ts
new file mode 100644
index 0000000000..3ac467c1ac
--- /dev/null
+++ b/packages/asset-swapper/test/market_utils_test.ts
@@ -0,0 +1,374 @@
+import * as chai from 'chai';
+import * as _ from 'lodash';
+import 'mocha';
+
+import { constants } from '../src/constants';
+import { marketUtils } from '../src/utils/market_utils';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrders } from './utils/test_orders';
+import { baseUnitAmount } from './utils/utils';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+// tslint:disable:custom-no-magic-numbers
+// tslint:disable: no-unused-expression
+describe('marketUtils', () => {
+ describe('#findOrdersThatCoverTakerAssetFillAmount', () => {
+ describe('no orders', () => {
+ it('returns empty and unchanged remainingFillAmount', async () => {
+ const fillAmount = baseUnitAmount(9);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ [],
+ fillAmount,
+ );
+ expect(resultOrders).to.be.empty;
+ expect(remainingFillAmount).to.be.bignumber.equal(fillAmount);
+ });
+ });
+ describe('orders do not have fees', () => {
+ const inputOrders = testOrders.PRUNED_SIGNED_ORDERS_FEELESS;
+ it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
+ const fillAmount = baseUnitAmount(5);
+ const slippageBufferAmount = baseUnitAmount(4);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(6);
+ const slippageBufferAmount = baseUnitAmount(3);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(10);
+ const slippageBufferAmount = baseUnitAmount(2);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ slippageBufferAmount,
+ );
+ expect(resultOrders).to.be.deep.equal(inputOrders);
+ expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(3));
+ });
+ it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
+ const fillAmount = baseUnitAmount(1);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(6);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ );
+ expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
+ expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ });
+ describe('orders have fees in takerAsset', () => {
+ const inputOrders = testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET;
+ it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
+ const fillAmount = baseUnitAmount(10);
+ const slippageBufferAmount = baseUnitAmount(5);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(6);
+ const slippageBufferAmount = baseUnitAmount(6);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(10);
+ const slippageBufferAmount = baseUnitAmount(6);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ slippageBufferAmount,
+ );
+ expect(resultOrders).to.be.deep.equal(inputOrders);
+ expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(1));
+ });
+ it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
+ const fillAmount = baseUnitAmount(4);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(9);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ );
+ expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
+ expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ });
+ describe('orders are feeless or have fees in takerAsset', () => {
+ const inputOrders = _.concat(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ );
+ it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
+ const fillAmount = baseUnitAmount(20);
+ const slippageBufferAmount = baseUnitAmount(4);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(10);
+ const slippageBufferAmount = baseUnitAmount(12);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(20);
+ const slippageBufferAmount = baseUnitAmount(6);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ slippageBufferAmount,
+ );
+ expect(resultOrders).to.be.deep.equal(inputOrders);
+ expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(2));
+ });
+ it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
+ const fillAmount = baseUnitAmount(4);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ );
+ expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
+ expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ it('returns first four orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => {
+ const fillAmount = baseUnitAmount(16);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverTakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ );
+ expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1], inputOrders[2], inputOrders[3]]);
+ expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ });
+ });
+ describe('#findOrdersThatCoverMakerAssetFillAmount', () => {
+ describe('no orders', () => {
+ it('returns empty and unchanged remainingFillAmount', async () => {
+ const fillAmount = baseUnitAmount(9);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ [],
+ fillAmount,
+ );
+ expect(resultOrders).to.be.empty;
+ expect(remainingFillAmount).to.be.bignumber.equal(fillAmount);
+ });
+ });
+ describe('orders do not have fees', () => {
+ const inputOrders = testOrders.PRUNED_SIGNED_ORDERS_FEELESS;
+ it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
+ const fillAmount = baseUnitAmount(6);
+ const slippageBufferAmount = baseUnitAmount(4);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(6);
+ const slippageBufferAmount = baseUnitAmount(3);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(10);
+ const slippageBufferAmount = baseUnitAmount(2);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ slippageBufferAmount,
+ );
+ expect(resultOrders).to.be.deep.equal(inputOrders);
+ expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(2));
+ });
+ it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
+ const fillAmount = baseUnitAmount(6);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(8);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ );
+ expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
+ expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ });
+ describe('orders have fees in makerAsset', () => {
+ const inputOrders = testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET;
+ it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
+ const fillAmount = baseUnitAmount(2);
+ const slippageBufferAmount = baseUnitAmount(3);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(4);
+ const slippageBufferAmount = baseUnitAmount(0.5);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(3);
+ const slippageBufferAmount = baseUnitAmount(3);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ slippageBufferAmount,
+ );
+ expect(resultOrders).to.be.deep.equal(inputOrders);
+ expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(1));
+ });
+ it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
+ const fillAmount = baseUnitAmount(1);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(2);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ );
+ expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
+ expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ });
+ describe('orders are feeless or have fees in makerAsset', () => {
+ const inputOrders = _.concat(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ );
+ it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
+ const fillAmount = baseUnitAmount(12);
+ const slippageBufferAmount = baseUnitAmount(3);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(12);
+ const slippageBufferAmount = baseUnitAmount(2);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ 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 () => {
+ const fillAmount = baseUnitAmount(14);
+ const slippageBufferAmount = baseUnitAmount(4);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ slippageBufferAmount,
+ );
+ expect(resultOrders).to.be.deep.equal(inputOrders);
+ expect(remainingFillAmount).to.be.bignumber.equal(baseUnitAmount(3));
+ });
+ it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => {
+ const fillAmount = baseUnitAmount(1);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ );
+ expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
+ expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ it('returns first four orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => {
+ const fillAmount = baseUnitAmount(11);
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ inputOrders,
+ fillAmount,
+ );
+ expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1], inputOrders[2], inputOrders[3]]);
+ expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ });
+ });
+});
diff --git a/packages/asset-swapper/test/order_prune_utils_test.ts b/packages/asset-swapper/test/order_prune_utils_test.ts
new file mode 100644
index 0000000000..6baf3d49e0
--- /dev/null
+++ b/packages/asset-swapper/test/order_prune_utils_test.ts
@@ -0,0 +1,336 @@
+import { ContractAddresses } from '@0x/contract-addresses';
+import { DevUtilsContract } from '@0x/contracts-dev-utils';
+import { ERC20TokenContract } from '@0x/contracts-erc20';
+import { ExchangeContract } from '@0x/contracts-exchange';
+import { constants as devConstants, getLatestBlockTimestampAsync, OrderFactory } from '@0x/contracts-test-utils';
+import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
+import { assetDataUtils } from '@0x/order-utils';
+import { SignedOrder } from '@0x/types';
+import { BigNumber } from '@0x/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { constants } from '../src/constants';
+import { OrderPrunerPermittedFeeTypes } from '../src/types';
+import { OrderPruner } from '../src/utils/order_prune_utils';
+
+import { chaiSetup } from './utils/chai_setup';
+import { migrateOnceAsync } from './utils/migrate';
+import { provider, web3Wrapper } from './utils/web3_wrapper';
+
+chaiSetup.configure();
+const expect = chai.expect;
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000);
+const TESTRPC_CHAIN_ID = devConstants.TESTRPC_CHAIN_ID;
+const GAS_PRICE = new BigNumber(devConstants.DEFAULT_GAS_PRICE);
+const PROTOCOL_FEE_PER_FILL = GAS_PRICE.times(constants.PROTOCOL_FEE_MULTIPLIER);
+const UNLIMITED_ALLOWANCE_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1); // tslint:disable-line:custom-no-magic-numbers
+
+// tslint:disable: no-unused-expression
+// tslint:disable: custom-no-magic-numbers
+describe('OrderPruner', () => {
+ let erc20MakerTokenContract: ERC20TokenContract;
+ let erc20TakerTokenContract: ERC20TokenContract;
+ let exchangeContract: ExchangeContract;
+ let devUtilsContract: DevUtilsContract;
+ let userAddresses: string[];
+ let coinbaseAddress: string;
+ let makerAddress: string;
+ let takerAddress: string;
+ let feeRecipient: string;
+ let makerTokenAddress: string;
+ let takerTokenAddress: string;
+ let makerAssetData: string;
+ let takerAssetData: string;
+ let orderFactory: OrderFactory;
+ let wethAssetData: string;
+ let contractAddresses: ContractAddresses;
+ let orderPruner: OrderPruner;
+
+ let nonOpenSignedOrder: SignedOrder;
+ let expiredOpenSignedOrder: SignedOrder;
+ let invalidSignatureOpenSignedOrder: SignedOrder;
+ let fullyFillableOpenSignedOrder: SignedOrder;
+ let partiallyFilledOpenSignedOrderFeeless: SignedOrder;
+ let partiallyFilledOpenSignedOrderFeeInTakerAsset: SignedOrder;
+ let partiallyFilledOpenSignedOrderFeeInMakerAsset: SignedOrder;
+ let filledOpenSignedOrder: SignedOrder;
+
+ const chainId = TESTRPC_CHAIN_ID;
+ const fillableAmount = new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI);
+ const partialFillAmount = new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI);
+ const takerFeeAmount = new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI);
+
+ before(async () => {
+ contractAddresses = await migrateOnceAsync();
+ await blockchainLifecycle.startAsync();
+ userAddresses = await web3Wrapper.getAvailableAddressesAsync();
+ [coinbaseAddress, takerAddress, makerAddress, feeRecipient] = userAddresses;
+ [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
+ erc20MakerTokenContract = new ERC20TokenContract(makerTokenAddress, provider);
+ erc20TakerTokenContract = new ERC20TokenContract(takerTokenAddress, provider);
+ [makerAssetData, takerAssetData, wethAssetData] = [
+ assetDataUtils.encodeERC20AssetData(makerTokenAddress),
+ assetDataUtils.encodeERC20AssetData(takerTokenAddress),
+ assetDataUtils.encodeERC20AssetData(contractAddresses.etherToken),
+ ];
+ exchangeContract = new ExchangeContract(contractAddresses.exchange, provider);
+ devUtilsContract = new DevUtilsContract(contractAddresses.devUtils, provider);
+ // Configure order defaults
+ const defaultOrderParams = {
+ ...devConstants.STATIC_ORDER_PARAMS,
+ makerAddress,
+ takerAddress: constants.NULL_ADDRESS,
+ makerAssetData,
+ takerAssetData,
+ makerFeeAssetData: constants.NULL_ERC20_ASSET_DATA,
+ takerFeeAssetData: constants.NULL_ERC20_ASSET_DATA,
+ makerFee: constants.ZERO_AMOUNT,
+ takerFee: constants.ZERO_AMOUNT,
+ feeRecipientAddress: feeRecipient,
+ exchangeAddress: contractAddresses.exchange,
+ chainId,
+ };
+ const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
+ orderFactory = new OrderFactory(privateKey, defaultOrderParams);
+ });
+ after(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+
+ nonOpenSignedOrder = await orderFactory.newSignedOrderAsync({
+ takerAddress,
+ });
+
+ expiredOpenSignedOrder = await orderFactory.newSignedOrderAsync({
+ expirationTimeSeconds: new BigNumber(await getLatestBlockTimestampAsync()).minus(10),
+ });
+
+ invalidSignatureOpenSignedOrder = await orderFactory.newSignedOrderAsync({
+ takerAddress,
+ });
+ invalidSignatureOpenSignedOrder.signature = constants.NULL_BYTES;
+
+ fullyFillableOpenSignedOrder = await orderFactory.newSignedOrderAsync({
+ takerAssetAmount: fillableAmount,
+ makerAssetAmount: fillableAmount,
+ });
+
+ // give double fillableAmount to maker and taker as buffer
+ await erc20MakerTokenContract
+ .transfer(makerAddress, fillableAmount.multipliedBy(4))
+ .sendTransactionAsync({ from: coinbaseAddress });
+ await erc20TakerTokenContract
+ .transfer(takerAddress, fillableAmount.multipliedBy(4))
+ .sendTransactionAsync({ from: coinbaseAddress });
+ await erc20MakerTokenContract
+ .approve(contractAddresses.erc20Proxy, UNLIMITED_ALLOWANCE_IN_BASE_UNITS)
+ .sendTransactionAsync({ from: makerAddress });
+ await erc20MakerTokenContract
+ .approve(contractAddresses.erc20Proxy, UNLIMITED_ALLOWANCE_IN_BASE_UNITS)
+ .sendTransactionAsync({ from: takerAddress });
+ await erc20TakerTokenContract
+ .approve(contractAddresses.erc20Proxy, UNLIMITED_ALLOWANCE_IN_BASE_UNITS)
+ .sendTransactionAsync({ from: takerAddress });
+
+ partiallyFilledOpenSignedOrderFeeless = await orderFactory.newSignedOrderAsync({
+ takerAssetAmount: fillableAmount,
+ makerAssetAmount: fillableAmount,
+ });
+
+ await exchangeContract
+ .fillOrKillOrder(
+ partiallyFilledOpenSignedOrderFeeless,
+ partialFillAmount,
+ partiallyFilledOpenSignedOrderFeeless.signature,
+ )
+ .sendTransactionAsync({
+ from: takerAddress,
+ gasPrice: GAS_PRICE,
+ gas: 4000000,
+ value: PROTOCOL_FEE_PER_FILL,
+ });
+
+ partiallyFilledOpenSignedOrderFeeInTakerAsset = await orderFactory.newSignedOrderAsync({
+ takerAssetAmount: fillableAmount,
+ makerAssetAmount: fillableAmount,
+ takerFee: takerFeeAmount,
+ takerFeeAssetData: takerAssetData,
+ });
+
+ await exchangeContract
+ .fillOrKillOrder(
+ partiallyFilledOpenSignedOrderFeeInTakerAsset,
+ partialFillAmount,
+ partiallyFilledOpenSignedOrderFeeInTakerAsset.signature,
+ )
+ .sendTransactionAsync({
+ from: takerAddress,
+ gasPrice: GAS_PRICE,
+ gas: 4000000,
+ value: PROTOCOL_FEE_PER_FILL,
+ });
+
+ partiallyFilledOpenSignedOrderFeeInMakerAsset = await orderFactory.newSignedOrderAsync({
+ takerAssetAmount: fillableAmount,
+ makerAssetAmount: fillableAmount,
+ takerFee: takerFeeAmount,
+ takerFeeAssetData: makerAssetData,
+ });
+
+ await exchangeContract
+ .fillOrKillOrder(
+ partiallyFilledOpenSignedOrderFeeInMakerAsset,
+ partialFillAmount,
+ partiallyFilledOpenSignedOrderFeeInMakerAsset.signature,
+ )
+ .sendTransactionAsync({
+ from: takerAddress,
+ gasPrice: GAS_PRICE,
+ gas: 4000000,
+ value: PROTOCOL_FEE_PER_FILL,
+ });
+
+ filledOpenSignedOrder = await orderFactory.newSignedOrderAsync({
+ takerAssetAmount: fillableAmount,
+ makerAssetAmount: fillableAmount,
+ });
+
+ await exchangeContract
+ .fillOrKillOrder(filledOpenSignedOrder, fillableAmount, filledOpenSignedOrder.signature)
+ .sendTransactionAsync({
+ from: takerAddress,
+ gasPrice: GAS_PRICE,
+ gas: 4000000,
+ value: PROTOCOL_FEE_PER_FILL,
+ });
+
+ orderPruner = new OrderPruner(devUtilsContract, {
+ permittedOrderFeeTypes: new Set([
+ OrderPrunerPermittedFeeTypes.NoFees,
+ OrderPrunerPermittedFeeTypes.MakerDenominatedTakerFee,
+ OrderPrunerPermittedFeeTypes.TakerDenominatedTakerFee,
+ ]),
+ });
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ describe('constructor options', () => {
+ it('should filter for only feeless orders if options permit only feeless orders', async () => {
+ orderPruner = new OrderPruner(devUtilsContract, {
+ permittedOrderFeeTypes: new Set([OrderPrunerPermittedFeeTypes.NoFees]),
+ });
+ const orders = [
+ partiallyFilledOpenSignedOrderFeeInMakerAsset,
+ partiallyFilledOpenSignedOrderFeeInTakerAsset,
+ partiallyFilledOpenSignedOrderFeeless,
+ ];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ // checks for one order in results and check for signature of orders
+ expect(resultPrunedOrders.length).to.be.equal(1);
+ expect(resultPrunedOrders[0].signature).to.be.deep.equal(partiallyFilledOpenSignedOrderFeeless.signature);
+ });
+ it('should filter for only takerFee in takerAsset orders if options permit only takerFee in takerAsset orders', async () => {
+ orderPruner = new OrderPruner(devUtilsContract, {
+ permittedOrderFeeTypes: new Set([
+ OrderPrunerPermittedFeeTypes.TakerDenominatedTakerFee,
+ ]),
+ });
+ const orders = [
+ partiallyFilledOpenSignedOrderFeeInMakerAsset,
+ partiallyFilledOpenSignedOrderFeeInTakerAsset,
+ partiallyFilledOpenSignedOrderFeeless,
+ ];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ // checks for one order in results and check for signature of orders
+ expect(resultPrunedOrders.length).to.be.equal(1);
+ expect(resultPrunedOrders[0].signature).to.be.deep.equal(
+ partiallyFilledOpenSignedOrderFeeInTakerAsset.signature,
+ );
+ });
+ it('should filter for only makerFee in takerAsset orders if options permit only makerFee orders', async () => {
+ orderPruner = new OrderPruner(devUtilsContract, {
+ permittedOrderFeeTypes: new Set([
+ OrderPrunerPermittedFeeTypes.MakerDenominatedTakerFee,
+ ]),
+ });
+ const orders = [
+ partiallyFilledOpenSignedOrderFeeInMakerAsset,
+ partiallyFilledOpenSignedOrderFeeInTakerAsset,
+ partiallyFilledOpenSignedOrderFeeless,
+ ];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ // checks for one order in results and check for signature of orders
+ expect(resultPrunedOrders.length).to.be.equal(1);
+ expect(resultPrunedOrders[0].signature).to.be.deep.equal(
+ partiallyFilledOpenSignedOrderFeeInMakerAsset.signature,
+ );
+ });
+ });
+ describe('#pruneSignedOrdersAsync', () => {
+ it('should filter out non open orders', async () => {
+ const orders = [nonOpenSignedOrder];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ expect(resultPrunedOrders).to.be.empty;
+ });
+ it('should filter out expired orders', async () => {
+ const orders = [expiredOpenSignedOrder];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ expect(resultPrunedOrders).to.be.empty;
+ });
+ it('should filter out invalid signature orders', async () => {
+ const orders = [invalidSignatureOpenSignedOrder];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ expect(resultPrunedOrders).to.be.empty;
+ });
+ it('should filter out fully filled orders', async () => {
+ const orders = [filledOpenSignedOrder];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ expect(resultPrunedOrders).to.be.empty;
+ });
+ it('should provide correct pruned signed orders for fully fillable orders', async () => {
+ const orders = [fullyFillableOpenSignedOrder];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ const prunedOrder = resultPrunedOrders[0];
+ expect(prunedOrder.fillableMakerAssetAmount).to.bignumber.equal(fillableAmount);
+ expect(prunedOrder.fillableTakerAssetAmount).to.bignumber.equal(fillableAmount);
+ });
+ it('should provide correct pruned signed orders for partially fillable orders', async () => {
+ const orders = [
+ partiallyFilledOpenSignedOrderFeeless,
+ partiallyFilledOpenSignedOrderFeeInTakerAsset,
+ partiallyFilledOpenSignedOrderFeeInMakerAsset,
+ ];
+ const resultPrunedOrders = await orderPruner.pruneSignedOrdersAsync(orders);
+ expect(resultPrunedOrders[0].fillableMakerAssetAmount).to.bignumber.equal(
+ fillableAmount.minus(partialFillAmount),
+ );
+ expect(resultPrunedOrders[0].fillableTakerAssetAmount).to.bignumber.equal(
+ fillableAmount.minus(partialFillAmount),
+ );
+ expect(resultPrunedOrders[1].fillableMakerAssetAmount).to.bignumber.equal(
+ fillableAmount.minus(partialFillAmount),
+ );
+ expect(resultPrunedOrders[1].fillableTakerAssetAmount).to.bignumber.equal(
+ fillableAmount.minus(partialFillAmount),
+ );
+ expect(resultPrunedOrders[1].fillableTakerFeeAmount).to.bignumber.equal(
+ new BigNumber(1.6).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ expect(resultPrunedOrders[2].fillableMakerAssetAmount).to.bignumber.equal(
+ fillableAmount.minus(partialFillAmount),
+ );
+ expect(resultPrunedOrders[2].fillableTakerAssetAmount).to.bignumber.equal(
+ fillableAmount.minus(partialFillAmount),
+ );
+ expect(resultPrunedOrders[2].fillableTakerFeeAmount).to.bignumber.equal(
+ new BigNumber(1.6).multipliedBy(ONE_ETH_IN_WEI),
+ );
+ });
+ });
+});
diff --git a/packages/asset-swapper/test/sorting_utils_test.ts b/packages/asset-swapper/test/sorting_utils_test.ts
new file mode 100644
index 0000000000..e11e03f35d
--- /dev/null
+++ b/packages/asset-swapper/test/sorting_utils_test.ts
@@ -0,0 +1,134 @@
+import { BigNumber } from '@0x/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { sortingUtils } from '../src/utils/sorting_utils';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrderFactory } from './utils/test_order_factory';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+const FAKE_ERC20_TAKER_ASSET_DATA = '0xf47261b22222222222222222222222222222222222222222222222222222222222222222';
+const FAKE_ERC20_MAKER_ASSET_DATA = '0xf47261b11111111111111111111111111111111111111111111111111111111111111111';
+
+describe('sortingUtils', () => {
+ describe('#sortOrders', () => {
+ // rate: 2 takerAsset / makerAsset
+ const testOrder1 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ // rate: 1 takerAsset / makerAsset
+ const testOrder2 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(100),
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ // rate: 2.5 takerAsset / makerAsset
+ const testOrder3 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(250),
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ // rate: 2 takerAsset / makerAsset
+ const testOrderWithFeeInTakerAsset1 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(100),
+ takerFee: new BigNumber(100),
+ takerFeeAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ // rate: 1 takerAsset / makerAsset
+ const testOrderWithFeeInTakerAsset2 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(50),
+ takerFee: new BigNumber(50),
+ takerFeeAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ // rate: 2.5 takerAsset / makerAsset
+ const testOrderWithFeeInTakerAsset3 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ takerFee: new BigNumber(50),
+ takerFeeAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ // rate: 2 takerAsset / makerAsset
+ const testOrderWithFeeInMakerAsset1 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(200),
+ takerAssetAmount: new BigNumber(200),
+ takerFee: new BigNumber(100),
+ takerFeeAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ // rate: 1 takerAsset / makerAsset
+ const testOrderWithFeeInMakerAsset2 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(150),
+ takerAssetAmount: new BigNumber(100),
+ takerFee: new BigNumber(50),
+ takerFeeAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ // rate: 2.5 takerAsset / makerAsset
+ const testOrderWithFeeInMakerAsset3 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(150),
+ takerAssetAmount: new BigNumber(250),
+ takerFee: new BigNumber(50),
+ takerFeeAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ });
+ it('correctly sorts by fee adjusted rate (feeless orders)', async () => {
+ const orders = [testOrder1, testOrder2, testOrder3];
+ const sortedOrders = sortingUtils.sortOrders(orders);
+ expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]);
+ });
+ it('correctly sorts by fee adjusted rate (takerAsset denominated fee orders)', async () => {
+ const orders = [
+ testOrderWithFeeInTakerAsset1,
+ testOrderWithFeeInTakerAsset2,
+ testOrderWithFeeInTakerAsset3,
+ ];
+ const sortedOrders = sortingUtils.sortOrders(orders);
+ expect(sortedOrders).to.deep.equal([
+ testOrderWithFeeInTakerAsset2,
+ testOrderWithFeeInTakerAsset1,
+ testOrderWithFeeInTakerAsset3,
+ ]);
+ });
+ it('correctly sorts by fee adjusted rate (makerAsset denominated fee orders)', async () => {
+ const orders = [
+ testOrderWithFeeInMakerAsset1,
+ testOrderWithFeeInMakerAsset2,
+ testOrderWithFeeInMakerAsset3,
+ ];
+ const sortedOrders = sortingUtils.sortOrders(orders);
+ expect(sortedOrders).to.deep.equal([
+ testOrderWithFeeInMakerAsset2,
+ testOrderWithFeeInMakerAsset1,
+ testOrderWithFeeInMakerAsset3,
+ ]);
+ });
+ it('correctly sorts by fee adjusted rate (mixed orders)', async () => {
+ const orders = [testOrderWithFeeInMakerAsset1, testOrderWithFeeInTakerAsset2, testOrder3];
+ const sortedOrders = sortingUtils.sortOrders(orders);
+ expect(sortedOrders).to.deep.equal([
+ testOrderWithFeeInTakerAsset2,
+ testOrderWithFeeInMakerAsset1,
+ testOrder3,
+ ]);
+ });
+ });
+});
diff --git a/packages/asset-swapper/test/swap_quote_calculator_test.ts b/packages/asset-swapper/test/swap_quote_calculator_test.ts
index a46ebd3c75..013aad277f 100644
--- a/packages/asset-swapper/test/swap_quote_calculator_test.ts
+++ b/packages/asset-swapper/test/swap_quote_calculator_test.ts
@@ -1,753 +1,581 @@
-import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
-import { SignedOrder } from '@0x/types';
+import { constants as devConstants } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
import 'mocha';
-import { constants } from '../src/constants';
-import { OrdersAndFillableAmounts, SwapQuoterError } from '../src/types';
import { swapQuoteCalculator } from '../src/utils/swap_quote_calculator';
import { chaiSetup } from './utils/chai_setup';
import { testHelpers } from './utils/test_helpers';
+import { testOrders } from './utils/test_orders';
+import { baseUnitAmount } from './utils/utils';
chaiSetup.configure();
const expect = chai.expect;
+const GAS_PRICE = new BigNumber(devConstants.DEFAULT_GAS_PRICE);
+const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000);
+const MIXED_TEST_ORDERS = _.concat(
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+);
+
// tslint:disable:max-file-line-count
// tslint:disable:custom-no-magic-numbers
describe('swapQuoteCalculator', () => {
describe('#calculateMarketSellSwapQuote', () => {
- let firstOrder: SignedOrder;
- let firstRemainingFillAmount: BigNumber;
- let secondOrder: SignedOrder;
- let secondRemainingFillAmount: BigNumber;
- let ordersAndFillableAmounts: OrdersAndFillableAmounts;
- let smallFeeOrderAndFillableAmount: OrdersAndFillableAmounts;
- let allFeeOrdersAndFillableAmounts: OrdersAndFillableAmounts;
- beforeEach(() => {
- // generate two orders for our desired maker asset
- // the first order has a rate of 4 makerAsset / WETH with a takerFee of 200 ZRX and has only 200 / 400 makerAsset units left to fill (half fillable)
- // the second order has a rate of 2 makerAsset / WETH with a takerFee of 100 ZRX and has 200 / 200 makerAsset units left to fill (completely fillable)
- // generate one order for fees
- // the fee order has a rate of 1 ZRX / WETH with no taker fee and has 100 ZRX left to fill (completely fillable)
- firstOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(400),
- takerAssetAmount: new BigNumber(100),
- takerFee: new BigNumber(200),
- });
- firstRemainingFillAmount = new BigNumber(200);
- secondOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(200),
- takerAssetAmount: new BigNumber(100),
- takerFee: new BigNumber(100),
- });
- secondRemainingFillAmount = secondOrder.makerAssetAmount;
- ordersAndFillableAmounts = {
- orders: [firstOrder, secondOrder],
- remainingFillableMakerAssetAmounts: [firstRemainingFillAmount, secondRemainingFillAmount],
- };
- const smallFeeOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(100),
- });
- smallFeeOrderAndFillableAmount = {
- orders: [smallFeeOrder],
- remainingFillableMakerAssetAmounts: [smallFeeOrder.makerAssetAmount],
- };
- const largeFeeOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(113),
- takerAssetAmount: new BigNumber(200),
- takerFee: new BigNumber(11),
- });
- allFeeOrdersAndFillableAmounts = {
- orders: [smallFeeOrder, largeFeeOrder],
- remainingFillableMakerAssetAmounts: [
- smallFeeOrder.makerAssetAmount,
- largeFeeOrder.makerAssetAmount.minus(largeFeeOrder.takerFee),
- ],
- };
- });
describe('InsufficientLiquidityError', () => {
- it('should throw if not enough taker asset liquidity (multiple orders)', () => {
- // we have 150 takerAsset units available to sell but attempt to calculate a quote for 200 takerAsset units
+ it('should throw if not enough taker asset liquidity (multiple feeless orders)', () => {
const errorFunction = () => {
swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(200),
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ baseUnitAmount(10),
0,
- false,
- false,
+ GAS_PRICE,
);
};
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(150));
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(9));
});
- it('should throw if not enough taker asset liquidity (multiple orders with 20% slippage)', () => {
- // we have 150 takerAsset units available to sell but attempt to calculate a quote for 200 takerAsset units
+ it('should throw if not enough taker asset liquidity (multiple feeless orders with 20% slippage)', () => {
const errorFunction = () => {
swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(200),
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ baseUnitAmount(10),
0.2,
- false,
- false,
+ GAS_PRICE,
);
};
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(125));
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(7.5));
});
- it('should throw if not enough taker asset liquidity (multiple orders with 5% slippage)', () => {
- // we have 150 takerAsset units available to fill but attempt to calculate a quote for 200 takerAsset units
+ it('should throw if not enough taker asset liquidity (multiple takerAsset denominated fee orders with no slippage)', () => {
const errorFunction = () => {
swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(200),
- 0.05,
- false,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(142));
- });
- it('should throw if not enough taker asset liquidity (partially filled order)', () => {
- const firstOrderAndFillableAmount: OrdersAndFillableAmounts = {
- orders: [firstOrder],
- remainingFillableMakerAssetAmounts: [firstRemainingFillAmount],
- };
-
- const errorFunction = () => {
- swapQuoteCalculator.calculateMarketSellSwapQuote(
- firstOrderAndFillableAmount,
- smallFeeOrderAndFillableAmount,
- new BigNumber(51),
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ baseUnitAmount(20),
0,
- false,
- false,
+ GAS_PRICE,
);
};
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(50));
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(15));
});
- it('should throw if not enough taker asset liquidity (completely fillable order)', () => {
- const completelyFillableOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(123),
- takerAssetAmount: new BigNumber(80),
- takerFee: new BigNumber(200),
- });
- const completelyFillableOrdersAndFillableAmount: OrdersAndFillableAmounts = {
- orders: [completelyFillableOrder],
- remainingFillableMakerAssetAmounts: [completelyFillableOrder.makerAssetAmount],
- };
+ it('should throw if not enough taker asset liquidity (multiple takerAsset denominated fee orders with 20% slippage)', () => {
const errorFunction = () => {
swapQuoteCalculator.calculateMarketSellSwapQuote(
- completelyFillableOrdersAndFillableAmount,
- smallFeeOrderAndFillableAmount,
- new BigNumber(81),
- 0,
- false,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(80));
- });
- it('should throw with 1 amount available if no slippage', () => {
- const smallOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(1),
- takerAssetAmount: new BigNumber(1),
- takerFee: new BigNumber(0),
- });
- const errorFunction = () => {
- swapQuoteCalculator.calculateMarketSellSwapQuote(
- { orders: [smallOrder], remainingFillableMakerAssetAmounts: [smallOrder.makerAssetAmount] },
- smallFeeOrderAndFillableAmount,
- new BigNumber(100),
- 0,
- false,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(1));
- });
- it('should throw with 0 available to fill if amount rounds to 0', () => {
- const smallOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(1),
- takerAssetAmount: new BigNumber(1),
- takerFee: new BigNumber(0),
- });
- const errorFunction = () => {
- swapQuoteCalculator.calculateMarketSellSwapQuote(
- { orders: [smallOrder], remainingFillableMakerAssetAmounts: [smallOrder.makerAssetAmount] },
- smallFeeOrderAndFillableAmount,
- new BigNumber(100),
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ baseUnitAmount(20),
0.2,
- false,
- false,
+ GAS_PRICE,
);
};
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(0));
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(12.5));
+ });
+ it('should throw if not enough taker asset liquidity (multiple makerAsset denominated fee orders with no slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketSellSwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ baseUnitAmount(10),
+ 0,
+ GAS_PRICE,
+ );
+ };
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(9));
+ });
+ it('should throw if not enough taker asset liquidity (multiple makerAsset denominated fee orders with 20% slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketSellSwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ baseUnitAmount(10),
+ 0.2,
+ GAS_PRICE,
+ );
+ };
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(7.5));
+ });
+ it('should throw if not enough taker asset liquidity (multiple mixed feeType orders with no slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketSellSwapQuote(
+ MIXED_TEST_ORDERS,
+ baseUnitAmount(40),
+ 0,
+ GAS_PRICE,
+ );
+ };
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(33));
+ });
+ it('should throw if not enough taker asset liquidity (multiple mixed feeTyoe orders with 20% slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketSellSwapQuote(
+ MIXED_TEST_ORDERS,
+ baseUnitAmount(40),
+ 0.2,
+ GAS_PRICE,
+ );
+ };
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(27.5));
});
});
- it('should not throw if order is fillable', () => {
- expect(() =>
- swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- allFeeOrdersAndFillableAmounts,
- new BigNumber(125),
- 0,
- false,
- false,
- ),
- ).to.not.throw();
- });
- it('should throw if not enough ZRX liquidity', () => {
- // we request 75 takerAsset units but the ZRX order is only enough to fill the first order, which only has 50 takerAsset units available
- expect(() =>
- swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(75),
- 0,
- false,
- false,
- ),
- ).to.throw(SwapQuoterError.InsufficientZrxLiquidity);
- });
- it('calculates a correct swapQuote with no slippage', () => {
- // we request 50 takerAsset units which can be filled using the first order
- // the first order requires a fee of 100 ZRX from the taker which can be filled by the feeOrder
- const assetSellAmount = new BigNumber(50);
+ it('calculates a correct swapQuote with no slippage (feeless orders)', () => {
+ const assetSellAmount = baseUnitAmount(0.5);
const slippagePercentage = 0;
const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
assetSellAmount,
slippagePercentage,
- false,
- false,
+ GAS_PRICE,
);
// test if orders are correct
- expect(swapQuote.orders).to.deep.equal([ordersAndFillableAmounts.orders[0]]);
- expect(swapQuote.feeOrders).to.deep.equal([smallFeeOrderAndFillableAmount.orders[0]]);
+ expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEELESS[0]]);
+ expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount);
+ // test if rates are correct
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0),
+ takerAssetAmount: assetSellAmount,
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(3),
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0),
+ takerAssetAmount: assetSellAmount,
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(3),
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ });
+ it('calculates a correct swapQuote with slippage (feeless orders)', () => {
+ const assetSellAmount = baseUnitAmount(1);
+ const slippagePercentage = 0.2;
+ const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ assetSellAmount,
+ slippagePercentage,
+ GAS_PRICE,
+ );
+ // test if orders are correct
+ expect(swapQuote.orders).to.deep.equal([
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS[0],
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS[1],
+ ]);
+ expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount);
+ // test if rates are correct
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0),
+ takerAssetAmount: assetSellAmount,
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(6),
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0),
+ takerAssetAmount: assetSellAmount,
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(0.4),
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
+ });
+ it('calculates a correct swapQuote with no slippage (takerAsset denominated fee orders)', () => {
+ const assetSellAmount = baseUnitAmount(4);
+ const slippagePercentage = 0;
+ const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ assetSellAmount,
+ slippagePercentage,
+ GAS_PRICE,
+ );
+ // test if orders are correct
+ expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET[0]]);
+ expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount);
+ // test if rates are correct
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(3),
+ takerAssetAmount: assetSellAmount.minus(baseUnitAmount(3)),
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(6),
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(3),
+ takerAssetAmount: assetSellAmount.minus(baseUnitAmount(3)),
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(6),
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ });
+ it('calculates a correct swapQuote with slippage (takerAsset denominated fee orders)', () => {
+ const assetSellAmount = baseUnitAmount(3);
+ const slippagePercentage = 0.5;
+ const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ assetSellAmount,
+ slippagePercentage,
+ GAS_PRICE,
+ );
+ // test if orders are correct
+ expect(swapQuote.orders).to.deep.equal([
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET[0],
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET[1],
+ ]);
+ expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount);
+ // test if rates are correct
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2.25),
+ takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2.25)),
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(4.5),
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0.5),
+ takerAssetAmount: assetSellAmount.minus(baseUnitAmount(0.5)),
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(1),
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
+ });
+ it('calculates a correct swapQuote with no slippage (makerAsset denominated fee orders)', () => {
+ const assetSellAmount = baseUnitAmount(4);
+ const slippagePercentage = 0;
+ const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ assetSellAmount,
+ slippagePercentage,
+ GAS_PRICE,
+ );
+ // test if orders are correct
+ expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET[0]]);
+ expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount);
+ // test if rates are correct
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2),
+ takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2)),
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(0.8),
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2),
+ takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2)),
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(0.8),
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ });
+ it('calculates a correct swapQuote with slippage (makerAsset denominated fee orders)', () => {
+ const assetSellAmount = baseUnitAmount(4);
+ const slippagePercentage = 0.5;
+ const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ assetSellAmount,
+ slippagePercentage,
+ GAS_PRICE,
+ );
+ // test if orders are correct
+ expect(swapQuote.orders).to.deep.equal([
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET[0],
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET[1],
+ ]);
+ expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount);
// test if rates are correct
// 50 takerAsset units to fill the first order + 100 takerAsset units for fees
- const expectedMakerAssetAmountForTakerAsset = new BigNumber(200);
- const expectedTakerAssetAmountForZrxFees = new BigNumber(100);
- const expectedTotalTakerAssetAmount = assetSellAmount.plus(expectedTakerAssetAmountForZrxFees);
- expect(swapQuote.bestCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(assetSellAmount);
- expect(swapQuote.bestCaseQuoteInfo.makerTokenAmount).to.bignumber.equal(
- expectedMakerAssetAmountForTakerAsset,
- );
- expect(swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(expectedTotalTakerAssetAmount);
- // because we have no slippage protection, minRate is equal to maxRate
- expect(swapQuote.worstCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(assetSellAmount);
- expect(swapQuote.worstCaseQuoteInfo.makerTokenAmount).to.bignumber.equal(
- expectedMakerAssetAmountForTakerAsset,
- );
- expect(swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(
- expectedTotalTakerAssetAmount,
- );
- });
- it('calculates a correct swapQuote with slippage', () => {
- // we request 50 takerAsset units which can be filled using the first order
- // however with 50% slippage we are protecting the buy with 25 extra takerAssetUnits
- // so we need enough orders to fill 75 takerAssetUnits
- // 75 takerAssetUnits can only be filled using both orders
- // the first order requires a fee of 100 ZRX from the taker which can be filled by the feeOrder
- const assetSellAmount = new BigNumber(50);
- const slippagePercentage = 0.5;
- const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- allFeeOrdersAndFillableAmounts,
- assetSellAmount,
- slippagePercentage,
- false,
- false,
- );
- // test if orders are correct
- expect(swapQuote.orders).to.deep.equal(ordersAndFillableAmounts.orders);
- expect(swapQuote.feeOrders).to.deep.equal(allFeeOrdersAndFillableAmounts.orders);
- // test if rates are correct
- const expectedMakerAssetAmountForTakerAsset = new BigNumber(200);
- const expectedTakerAssetAmountForZrxFees = new BigNumber(100);
- const expectedTotalTakerAssetAmount = assetSellAmount.plus(expectedTakerAssetAmountForZrxFees);
- expect(swapQuote.bestCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(assetSellAmount);
- expect(swapQuote.bestCaseQuoteInfo.makerTokenAmount).to.bignumber.equal(
- expectedMakerAssetAmountForTakerAsset,
- );
- expect(swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(expectedTotalTakerAssetAmount);
-
- const expectedWorstMakerAssetAmountForTakerAsset = new BigNumber(100);
- const expectedWorstTakerAssetAmountForZrxFees = new BigNumber(99);
- const expectedWorstTotalTakerAssetAmount = assetSellAmount.plus(expectedWorstTakerAssetAmountForZrxFees);
- expect(swapQuote.worstCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(assetSellAmount);
- expect(swapQuote.worstCaseQuoteInfo.makerTokenAmount).to.bignumber.equal(
- expectedWorstMakerAssetAmountForTakerAsset,
- );
- expect(swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(
- expectedWorstTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(
- expectedWorstTotalTakerAssetAmount,
- );
- });
- it('calculates a correct swapQuote (with fee calculations disabled) with no slippage', () => {
- // we request 50 takerAsset units which can be filled using the first order
- const assetSellAmount = new BigNumber(50);
- const slippagePercentage = 0;
- const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- assetSellAmount,
- slippagePercentage,
- false,
- true,
- );
- // test if orders are correct
- expect(swapQuote.orders).to.deep.equal([ordersAndFillableAmounts.orders[0]]);
- expect(swapQuote.feeOrders).to.deep.equal([]);
- // test if rates are correct
- const expectedMakerAssetAmountForTakerAsset = new BigNumber(200);
- const expectedTotalTakerAssetAmount = assetSellAmount;
- expect(swapQuote.bestCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(assetSellAmount);
- expect(swapQuote.bestCaseQuoteInfo.makerTokenAmount).to.bignumber.equal(
- expectedMakerAssetAmountForTakerAsset,
- );
- expect(swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(expectedTotalTakerAssetAmount);
- // because we have no slippage protection, minRate is equal to maxRate
- expect(swapQuote.worstCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(assetSellAmount);
- expect(swapQuote.worstCaseQuoteInfo.makerTokenAmount).to.bignumber.equal(
- expectedMakerAssetAmountForTakerAsset,
- );
- expect(swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(
- expectedTotalTakerAssetAmount,
- );
- });
- it('calculates a correct swapQuote (with fee calculatations disabled) with slippage', () => {
- // we request 50 takerAsset units which can be filled using the first order
- // however with 50% slippage we are protecting the buy with 25 extra takerAssetUnits
- // so we need enough orders to fill 75 takerAssetUnits
- // 50 takerAssetUnits can only be filled using both orders
- // the first order requires a fee of 100 ZRX from the taker which can be filled by the feeOrder
- const assetSellAmount = new BigNumber(50);
- const slippagePercentage = 0.5;
- const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote(
- ordersAndFillableAmounts,
- allFeeOrdersAndFillableAmounts,
- assetSellAmount,
- slippagePercentage,
- false,
- true,
- );
- // test if orders are correct
- expect(swapQuote.orders).to.deep.equal(ordersAndFillableAmounts.orders);
- expect(swapQuote.feeOrders).to.deep.equal([]);
- // test if rates are correct
- const expectedMakerAssetAmountForTakerAsset = new BigNumber(200);
- const expectedTotalTakerAssetAmount = assetSellAmount;
- expect(swapQuote.bestCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(assetSellAmount);
- expect(swapQuote.bestCaseQuoteInfo.makerTokenAmount).to.bignumber.equal(
- expectedMakerAssetAmountForTakerAsset,
- );
- expect(swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(expectedTotalTakerAssetAmount);
- // 100 eth to fill the first order + 208 eth for fees
- const expectedWorstMakerAssetAmountForTakerAsset = new BigNumber(100);
- const expectedWorstTotalTakerAssetAmount = assetSellAmount;
- expect(swapQuote.worstCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(assetSellAmount);
- expect(swapQuote.worstCaseQuoteInfo.makerTokenAmount).to.bignumber.equal(
- expectedWorstMakerAssetAmountForTakerAsset,
- );
- expect(swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(
- expectedWorstTotalTakerAssetAmount,
- );
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2),
+ takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2)),
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(0.8),
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2),
+ takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2)),
+ totalTakerAssetAmount: assetSellAmount,
+ makerAssetAmount: baseUnitAmount(3.6),
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
});
});
describe('#calculateMarketBuySwapQuote', () => {
- let firstOrder: SignedOrder;
- let firstRemainingFillAmount: BigNumber;
- let secondOrder: SignedOrder;
- let secondRemainingFillAmount: BigNumber;
- let ordersAndFillableAmounts: OrdersAndFillableAmounts;
- let smallFeeOrderAndFillableAmount: OrdersAndFillableAmounts;
- let allFeeOrdersAndFillableAmounts: OrdersAndFillableAmounts;
- beforeEach(() => {
- // generate two orders for our desired maker asset
- // the first order has a rate of 4 makerAsset / WETH with a takerFee of 200 ZRX and has only 200 / 400 makerAsset units left to fill (half fillable)
- // the second order has a rate of 2 makerAsset / WETH with a takerFee of 100 ZRX and has 200 / 200 makerAsset units left to fill (completely fillable)
- // generate one order for fees
- // the fee order has a rate of 1 ZRX / WETH with no taker fee and has 100 ZRX left to fill (completely fillable)
- firstOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(400),
- takerAssetAmount: new BigNumber(100),
- takerFee: new BigNumber(200),
- });
- firstRemainingFillAmount = new BigNumber(200);
- secondOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(200),
- takerAssetAmount: new BigNumber(100),
- takerFee: new BigNumber(100),
- });
- secondRemainingFillAmount = secondOrder.makerAssetAmount;
- ordersAndFillableAmounts = {
- orders: [firstOrder, secondOrder],
- remainingFillableMakerAssetAmounts: [firstRemainingFillAmount, secondRemainingFillAmount],
- };
- const smallFeeOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(100),
- });
- smallFeeOrderAndFillableAmount = {
- orders: [smallFeeOrder],
- remainingFillableMakerAssetAmounts: [smallFeeOrder.makerAssetAmount],
- };
- const largeFeeOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(113),
- takerAssetAmount: new BigNumber(200),
- takerFee: new BigNumber(11),
- });
- allFeeOrdersAndFillableAmounts = {
- orders: [smallFeeOrder, largeFeeOrder],
- remainingFillableMakerAssetAmounts: [
- smallFeeOrder.makerAssetAmount,
- largeFeeOrder.makerAssetAmount.minus(largeFeeOrder.takerFee),
- ],
- };
- });
describe('InsufficientLiquidityError', () => {
- it('should throw if not enough maker asset liquidity (multiple orders)', () => {
- // we have 400 makerAsset units available to fill but attempt to calculate a quote for 500 makerAsset units
+ it('should throw if not enough maker asset liquidity (multiple feeless orders)', () => {
const errorFunction = () => {
swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(500),
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ baseUnitAmount(12),
0,
- false,
- false,
+ GAS_PRICE,
);
};
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(400));
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(10));
});
- it('should throw if not enough maker asset liquidity (multiple orders with 20% slippage)', () => {
- // we have 400 makerAsset units available to fill but attempt to calculate a quote for 500 makerAsset units
+ it('should throw if not enough taker asset liquidity (multiple feeless orders with 20% slippage)', () => {
const errorFunction = () => {
swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(500),
- 0.2,
- false,
- false,
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ baseUnitAmount(10),
+ 0.6,
+ GAS_PRICE,
);
};
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(333));
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(6.25));
});
- it('should throw if not enough maker asset liquidity (multiple orders with 5% slippage)', () => {
- // we have 400 makerAsset units available to fill but attempt to calculate a quote for 500 makerAsset units
+ it('should throw if not enough taker asset liquidity (multiple takerAsset denominated fee orders with no slippage)', () => {
const errorFunction = () => {
swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(600),
- 0.05,
- false,
- false,
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ baseUnitAmount(12),
+ 0,
+ GAS_PRICE,
);
};
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(380));
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(10));
});
- it('should throw if not enough maker asset liquidity (partially filled order)', () => {
- const firstOrderAndFillableAmount: OrdersAndFillableAmounts = {
- orders: [firstOrder],
- remainingFillableMakerAssetAmounts: [firstRemainingFillAmount],
+ it('should throw if not enough taker asset liquidity (multiple takerAsset denominated fee orders with 20% slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketBuySwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ baseUnitAmount(12),
+ 0.6,
+ GAS_PRICE,
+ );
};
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(6.25));
+ });
+ it('should throw if not enough taker asset liquidity (multiple makerAsset denominated fee orders with no slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketBuySwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ baseUnitAmount(6),
+ 0,
+ GAS_PRICE,
+ );
+ };
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(5));
+ });
+ it('should throw if not enough taker asset liquidity (multiple makerAsset denominated fee orders with 20% slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketBuySwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+ baseUnitAmount(6),
+ 0.6,
+ GAS_PRICE,
+ );
+ };
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(3.125));
+ });
+ it('should throw if not enough taker asset liquidity (multiple mixed feeType orders with no slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketBuySwapQuote(
+ MIXED_TEST_ORDERS,
+ baseUnitAmount(40),
+ 0,
+ GAS_PRICE,
+ );
+ };
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(25));
+ });
+ it('should throw if not enough taker asset liquidity (multiple mixed feeTyoe orders with 20% slippage)', () => {
+ const errorFunction = () => {
+ swapQuoteCalculator.calculateMarketBuySwapQuote(
+ MIXED_TEST_ORDERS,
+ baseUnitAmount(40),
+ 0.6,
+ GAS_PRICE,
+ );
+ };
+ testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(15.625));
+ });
+ });
+ it('calculates a correct swapQuote with no slippage (feeless orders)', () => {
+ const assetBuyAmount = baseUnitAmount(3);
+ const slippagePercentage = 0;
+ const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ assetBuyAmount,
+ slippagePercentage,
+ GAS_PRICE,
+ );
+ // test if orders are correct
+ expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEELESS[0]]);
+ expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount);
+ // test if rates are correct
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0),
+ takerAssetAmount: baseUnitAmount(0.5),
+ totalTakerAssetAmount: baseUnitAmount(0.5),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0),
+ takerAssetAmount: baseUnitAmount(0.5),
+ totalTakerAssetAmount: baseUnitAmount(0.5),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ });
+ it('calculates a correct swapQuote with slippage (feeless orders)', () => {
+ const assetBuyAmount = baseUnitAmount(5);
+ const slippagePercentage = 0.5;
+ const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote(
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS,
+ assetBuyAmount,
+ slippagePercentage,
+ GAS_PRICE,
+ );
+ // test if orders are correct
+ expect(swapQuote.orders).to.deep.equal([
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS[0],
+ testOrders.PRUNED_SIGNED_ORDERS_FEELESS[1],
+ ]);
+ expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount);
- const errorFunction = () => {
- swapQuoteCalculator.calculateMarketBuySwapQuote(
- firstOrderAndFillableAmount,
- smallFeeOrderAndFillableAmount,
- new BigNumber(201),
- 0,
- false,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(200));
+ const takerAssetAmount = new BigNumber(5)
+ .div(new BigNumber(6))
+ .multipliedBy(ONE_ETH_IN_WEI)
+ .integerValue(BigNumber.ROUND_CEIL);
+ // test if rates are correct
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0),
+ takerAssetAmount,
+ totalTakerAssetAmount: takerAssetAmount,
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
});
- it('should throw if not enough maker asset liquidity (completely fillable order)', () => {
- const completelyFillableOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(123),
- takerAssetAmount: new BigNumber(100),
- takerFee: new BigNumber(200),
- });
- const completelyFillableOrdersAndFillableAmount: OrdersAndFillableAmounts = {
- orders: [completelyFillableOrder],
- remainingFillableMakerAssetAmounts: [completelyFillableOrder.makerAssetAmount],
- };
- const errorFunction = () => {
- swapQuoteCalculator.calculateMarketBuySwapQuote(
- completelyFillableOrdersAndFillableAmount,
- smallFeeOrderAndFillableAmount,
- new BigNumber(124),
- 0,
- false,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(123));
- });
- it('should throw with 1 amount available if no slippage', () => {
- const smallOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(1),
- takerAssetAmount: new BigNumber(1),
- takerFee: new BigNumber(0),
- });
- const errorFunction = () => {
- swapQuoteCalculator.calculateMarketBuySwapQuote(
- { orders: [smallOrder], remainingFillableMakerAssetAmounts: [smallOrder.makerAssetAmount] },
- smallFeeOrderAndFillableAmount,
- new BigNumber(600),
- 0,
- false,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(1));
- });
- it('should throw with 0 available to fill if amount rounds to 0', () => {
- const smallOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: new BigNumber(1),
- takerAssetAmount: new BigNumber(1),
- takerFee: new BigNumber(0),
- });
- const errorFunction = () => {
- swapQuoteCalculator.calculateMarketBuySwapQuote(
- { orders: [smallOrder], remainingFillableMakerAssetAmounts: [smallOrder.makerAssetAmount] },
- smallFeeOrderAndFillableAmount,
- new BigNumber(600),
- 0.2,
- false,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(0));
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(0),
+ takerAssetAmount: baseUnitAmount(5.5),
+ totalTakerAssetAmount: baseUnitAmount(5.5),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
});
});
- it('should not throw if order is fillable', () => {
- expect(() =>
- swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- allFeeOrdersAndFillableAmounts,
- new BigNumber(300),
- 0,
- false,
- false,
- ),
- ).to.not.throw();
- });
- it('should throw if not enough ZRX liquidity', () => {
- // we request 300 makerAsset units but the ZRX order is only enough to fill the first order, which only has 200 makerAssetUnits available
- expect(() =>
- swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(300),
- 0,
- false,
- false,
- ),
- ).to.throw(SwapQuoterError.InsufficientZrxLiquidity);
- });
- it('calculates a correct swapQuote with no slippage', () => {
- // we request 200 makerAsset units which can be filled using the first order
- // the first order requires a fee of 100 ZRX from the taker which can be filled by the feeOrder
- const assetBuyAmount = new BigNumber(200);
+ it('calculates a correct swapQuote with no slippage (takerAsset denominated fee orders)', () => {
+ const assetBuyAmount = baseUnitAmount(3);
const slippagePercentage = 0;
const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
assetBuyAmount,
slippagePercentage,
- false,
- false,
+ GAS_PRICE,
);
// test if orders are correct
- expect(swapQuote.orders).to.deep.equal([ordersAndFillableAmounts.orders[0]]);
- expect(swapQuote.feeOrders).to.deep.equal([smallFeeOrderAndFillableAmount.orders[0]]);
+ expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET[0]]);
+ expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount);
// test if rates are correct
- // 50 eth to fill the first order + 100 eth for fees
- const expectedTakerAssetAmountForMakerAsset = new BigNumber(50);
- const expectedTakerAssetAmountForZrxFees = new BigNumber(100);
- const expectedTotalTakerAssetAmount = expectedTakerAssetAmountForMakerAsset.plus(
- expectedTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.bestCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForMakerAsset,
- );
- expect(swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(expectedTotalTakerAssetAmount);
- // because we have no slippage protection, minRate is equal to maxRate
- expect(swapQuote.worstCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForMakerAsset,
- );
- expect(swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(
- expectedTotalTakerAssetAmount,
- );
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(1.5),
+ takerAssetAmount: baseUnitAmount(0.5),
+ totalTakerAssetAmount: baseUnitAmount(2),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(1.5),
+ takerAssetAmount: baseUnitAmount(0.5),
+ totalTakerAssetAmount: baseUnitAmount(2),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
});
- it('calculates a correct swapQuote with slippage', () => {
- // we request 200 makerAsset units which can be filled using the first order
- // however with 50% slippage we are protecting the buy with 100 extra makerAssetUnits
- // so we need enough orders to fill 300 makerAssetUnits
- // 300 makerAssetUnits can only be filled using both orders
- // the first order requires a fee of 100 ZRX from the taker which can be filled by the feeOrder
- const assetBuyAmount = new BigNumber(200);
+ it('calculates a correct swapQuote with slippage (takerAsset denominated fee orders)', () => {
+ const assetBuyAmount = baseUnitAmount(5);
const slippagePercentage = 0.5;
const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- allFeeOrdersAndFillableAmounts,
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
assetBuyAmount,
slippagePercentage,
- false,
- false,
+ GAS_PRICE,
);
+ const fiveSixthEthInWei = new BigNumber(5)
+ .div(new BigNumber(6))
+ .multipliedBy(ONE_ETH_IN_WEI)
+ .integerValue(BigNumber.ROUND_CEIL);
// test if orders are correct
- expect(swapQuote.orders).to.deep.equal(ordersAndFillableAmounts.orders);
- expect(swapQuote.feeOrders).to.deep.equal(allFeeOrdersAndFillableAmounts.orders);
+ expect(swapQuote.orders).to.deep.equal([
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET[0],
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET[1],
+ ]);
+ expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount);
// test if rates are correct
- // 50 eth to fill the first order + 100 eth for fees
- const expectedTakerAssetAmountForMakerAsset = new BigNumber(50);
- const expectedTakerAssetAmountForZrxFees = new BigNumber(100);
- const expectedTotalTakerAssetAmount = expectedTakerAssetAmountForMakerAsset.plus(
- expectedTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.bestCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForMakerAsset,
- );
- expect(swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(expectedTotalTakerAssetAmount);
- // 100 eth to fill the first order + 208 eth for fees
- const expectedWorstTakerAssetAmountForMakerAsset = new BigNumber(100);
- const expectedWorstTakerAssetAmountForZrxFees = new BigNumber(208);
- const expectedWorstTotalTakerAssetAmount = expectedWorstTakerAssetAmountForMakerAsset.plus(
- expectedWorstTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.worstCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(
- expectedWorstTakerAssetAmountForMakerAsset,
- );
- expect(swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(
- expectedWorstTakerAssetAmountForZrxFees,
- );
- expect(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(
- expectedWorstTotalTakerAssetAmount,
- );
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2.5),
+ takerAssetAmount: fiveSixthEthInWei,
+ totalTakerAssetAmount: baseUnitAmount(2.5).plus(fiveSixthEthInWei),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2.5),
+ takerAssetAmount: baseUnitAmount(5.5),
+ totalTakerAssetAmount: baseUnitAmount(8),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
});
- it('calculates a correct swapQuote (with fee calculations disabled) with no slippage', () => {
- // we request 200 makerAsset units which can be filled using the first order
- // the first order requires a fee of 100 ZRX from the taker which can be filled by the feeOrder
- const assetBuyAmount = new BigNumber(200);
+ it('calculates a correct swapQuote with no slippage (makerAsset denominated fee orders)', () => {
+ const assetBuyAmount = baseUnitAmount(1);
const slippagePercentage = 0;
const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
assetBuyAmount,
slippagePercentage,
- false,
- true,
+ GAS_PRICE,
);
// test if orders are correct
- expect(swapQuote.orders).to.deep.equal([ordersAndFillableAmounts.orders[0]]);
- expect(swapQuote.feeOrders).to.deep.equal([]);
+ expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET[0]]);
+ expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount);
// test if rates are correct
- // 50 eth to fill the first order + 100 eth for fees
- const expectedTakerAssetAmountForMakerAsset = new BigNumber(50);
- const expectedTotalTakerAssetAmount = expectedTakerAssetAmountForMakerAsset;
- expect(swapQuote.bestCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForMakerAsset,
- );
- expect(swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(expectedTotalTakerAssetAmount);
- // because we have no slippage protection, minRate is equal to maxRate
- expect(swapQuote.worstCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForMakerAsset,
- );
- expect(swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(
- expectedTotalTakerAssetAmount,
- );
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2.5),
+ takerAssetAmount: baseUnitAmount(2.5),
+ totalTakerAssetAmount: baseUnitAmount(5),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2.5),
+ takerAssetAmount: baseUnitAmount(2.5),
+ totalTakerAssetAmount: baseUnitAmount(5),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(15, 4),
+ });
});
- it('calculates a correct swapQuote (with fee calculations disabled) with slippage', () => {
- // we request 200 makerAsset units which can be filled using the first order
- // however with 50% slippage we are protecting the buy with 100 extra makerAssetUnits
- // so we need enough orders to fill 300 makerAssetUnits
- // 300 makerAssetUnits can only be filled using both orders
- // the first order requires a fee of 100 ZRX from the taker which can be filled by the feeOrder
- const assetBuyAmount = new BigNumber(200);
+ it('calculates a correct swapQuote with slippage (makerAsset denominated fee orders)', () => {
+ const assetBuyAmount = baseUnitAmount(2.5);
const slippagePercentage = 0.5;
const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote(
- ordersAndFillableAmounts,
- allFeeOrdersAndFillableAmounts,
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
assetBuyAmount,
slippagePercentage,
- false,
- true,
+ GAS_PRICE,
);
+ const totalTakerAssetAmount = new BigNumber(5)
+ .div(new BigNumber(6))
+ .multipliedBy(ONE_ETH_IN_WEI)
+ .integerValue(BigNumber.ROUND_CEIL);
// test if orders are correct
- expect(swapQuote.orders).to.deep.equal(ordersAndFillableAmounts.orders);
- expect(swapQuote.feeOrders).to.deep.equal([]);
+ expect(swapQuote.orders).to.deep.equal([
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET[0],
+ testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET[1],
+ ]);
+ expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount);
// test if rates are correct
- // 50 eth to fill the first order + 100 eth for fees
- const expectedTakerAssetAmountForMakerAsset = new BigNumber(50);
- const expectedTotalTakerAssetAmount = expectedTakerAssetAmountForMakerAsset;
- expect(swapQuote.bestCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(
- expectedTakerAssetAmountForMakerAsset,
- );
- expect(swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(expectedTotalTakerAssetAmount);
- // 100 eth to fill the first order + 208 eth for fees
- const expectedWorstTakerAssetAmountForMakerAsset = new BigNumber(100);
- const expectedWorstTotalTakerAssetAmount = expectedWorstTakerAssetAmountForMakerAsset;
- expect(swapQuote.worstCaseQuoteInfo.takerTokenAmount).to.bignumber.equal(
- expectedWorstTakerAssetAmountForMakerAsset,
- );
- expect(swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
- expect(swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount).to.bignumber.equal(
- expectedWorstTotalTakerAssetAmount,
- );
+ // 50 takerAsset units to fill the first order + 100 takerAsset units for fees
+ expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: baseUnitAmount(2.75),
+ takerAssetAmount: baseUnitAmount(2.75),
+ totalTakerAssetAmount: baseUnitAmount(5.5),
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
+ expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({
+ feeTakerAssetAmount: totalTakerAssetAmount.div(2),
+ takerAssetAmount: totalTakerAssetAmount.div(2),
+ totalTakerAssetAmount,
+ makerAssetAmount: assetBuyAmount,
+ protocolFeeInEthAmount: baseUnitAmount(30, 4),
+ });
});
});
});
diff --git a/packages/asset-swapper/test/swap_quote_consumer_test.ts b/packages/asset-swapper/test/swap_quote_consumer_test.ts
deleted file mode 100644
index 69cc975158..0000000000
--- a/packages/asset-swapper/test/swap_quote_consumer_test.ts
+++ /dev/null
@@ -1,176 +0,0 @@
-import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers';
-import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
-import { MarketOperation, SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import * as chai from 'chai';
-import 'mocha';
-
-import { SwapQuote, SwapQuoteConsumer } from '../src';
-import { ExtensionContractType } from '../src/types';
-
-import { chaiSetup } from './utils/chai_setup';
-import { migrateOnceAsync } from './utils/migrate';
-import { getFullyFillableSwapQuoteWithNoFees, getSignedOrdersWithNoFeesAsync } from './utils/swap_quote';
-import { provider, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000);
-const TESTRPC_CHAIN_ID = 1337;
-const FILLABLE_AMOUNTS = [new BigNumber(3), new BigNumber(2), new BigNumber(5)].map(value =>
- value.multipliedBy(ONE_ETH_IN_WEI),
-);
-
-const UNLIMITED_ALLOWANCE_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1); // tslint:disable-line:custom-no-magic-numbers
-
-describe('SwapQuoteConsumer', () => {
- let contractWrappers: ContractWrappers;
- let erc20Token: ERC20TokenContract;
- let userAddresses: string[];
- let coinbaseAddress: string;
- let makerAddress: string;
- let takerAddress: string;
- let feeRecipient: string;
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let makerAssetData: string;
- let takerAssetData: string;
- let wethAssetData: string;
- let contractAddresses: ContractAddresses;
-
- const chainId = TESTRPC_CHAIN_ID;
-
- let orders: SignedOrder[];
- let marketSellSwapQuote: SwapQuote;
- let swapQuoteConsumer: SwapQuoteConsumer;
- let erc20ProxyAddress: string;
-
- before(async () => {
- contractAddresses = await migrateOnceAsync();
- await blockchainLifecycle.startAsync();
- userAddresses = await web3Wrapper.getAvailableAddressesAsync();
- const config = {
- chainId,
- contractAddresses,
- };
- contractWrappers = new ContractWrappers(provider, config);
- [coinbaseAddress, takerAddress, makerAddress, feeRecipient] = userAddresses;
- [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
- erc20Token = new ERC20TokenContract(makerTokenAddress, provider);
- [makerAssetData, takerAssetData, wethAssetData] = [
- await contractWrappers.devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
- await contractWrappers.devUtils.encodeERC20AssetData(takerTokenAddress).callAsync(),
- await contractWrappers.devUtils.encodeERC20AssetData(contractAddresses.etherToken).callAsync(),
- ];
- });
- after(async () => {
- await blockchainLifecycle.revertAsync();
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- const UNLIMITED_ALLOWANCE = UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
- erc20ProxyAddress = contractAddresses.erc20Proxy;
-
- const totalFillableAmount = FILLABLE_AMOUNTS.reduce(
- (a: BigNumber, c: BigNumber) => a.plus(c),
- new BigNumber(0),
- );
-
- await erc20Token.transfer(makerAddress, totalFillableAmount).sendTransactionAsync({
- from: coinbaseAddress,
- });
-
- await erc20Token.approve(erc20ProxyAddress, UNLIMITED_ALLOWANCE).sendTransactionAsync({
- from: makerAddress,
- });
- orders = await getSignedOrdersWithNoFeesAsync(
- provider,
- makerAssetData,
- wethAssetData,
- makerAddress,
- takerAddress,
- FILLABLE_AMOUNTS,
- contractAddresses.exchange,
- );
-
- marketSellSwapQuote = getFullyFillableSwapQuoteWithNoFees(
- makerAssetData,
- wethAssetData,
- orders,
- MarketOperation.Sell,
- );
-
- swapQuoteConsumer = new SwapQuoteConsumer(provider, {
- chainId,
- });
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- // TODO(david): write tests to ensure options work for executeSwapQuote
- // describe('executeSwapQuoteOrThrowAsync', () => {
- // /*
- // * Testing that SwapQuoteConsumer logic correctly performs a execution (doesn't throw or revert)
- // * Does not test the validity of the state change performed by the forwarder smart contract
- // */
- // it('should perform an asset swap with Forwarder contract when provided corresponding useExtensionContract option', async () => {
- // let makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- // let takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- // expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- // expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- // await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, { takerAddress, useExtensionContract: ConsumerType.Forwarder });
- // makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- // takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- // expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- // expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- // });
- // it('should perform an asset swap with Exchange contract when provided corresponding useExtensionContract option', async () => {
- // let makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- // let takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- // expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- // expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- // await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, { takerAddress });
- // makerBalance = await erc20TokenContract.balanceOf(makerAddress).callAsync();
- // takerBalance = await erc20TokenContract.balanceOf(takerAddress).callAsync();
- // expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
- // expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
- // });
- // });
-
- describe('getSmartContractParamsOrThrow', () => {
- describe('valid swap quote', async () => {
- // TODO(david) Check for valid MethodAbi
- it('should provide correct and optimized smart contract params for Forwarder contract when provided corresponding useExtensionContract option', async () => {
- const { toAddress } = await swapQuoteConsumer.getSmartContractParamsOrThrowAsync(marketSellSwapQuote, {
- useExtensionContract: ExtensionContractType.Forwarder,
- });
- expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
- });
- it('should provide correct and optimized smart contract params for Exchange contract when provided corresponding useExtensionContract option', async () => {
- const { toAddress } = await swapQuoteConsumer.getSmartContractParamsOrThrowAsync(marketSellSwapQuote, {
- useExtensionContract: ExtensionContractType.None,
- });
- expect(toAddress).to.deep.equal(contractWrappers.exchange.address);
- });
- });
- });
-
- describe('getCalldataOrThrow', () => {
- describe('valid swap quote', async () => {
- it('should provide correct and optimized calldata options for Forwarder contract when provided corresponding useExtensionContract option', async () => {
- const { toAddress } = await swapQuoteConsumer.getCalldataOrThrowAsync(marketSellSwapQuote, {
- useExtensionContract: ExtensionContractType.Forwarder,
- });
- expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
- });
- it('should provide correct and optimized smart contract params for Exchange contract when provided corresponding useExtensionContract option', async () => {
- const { toAddress } = await swapQuoteConsumer.getCalldataOrThrowAsync(marketSellSwapQuote, {
- useExtensionContract: ExtensionContractType.None,
- });
- expect(toAddress).to.deep.equal(contractWrappers.exchange.address);
- });
- });
- });
-});
diff --git a/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts b/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts
index cc9b02728f..24bf29a785 100644
--- a/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts
+++ b/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts
@@ -1,16 +1,19 @@
-import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
+import { ContractAddresses } from '@0x/contract-addresses';
+import { DevUtilsContract } from '@0x/contracts-dev-utils';
+import { WETH9Contract } from '@0x/contracts-erc20';
+import { constants as devConstants, OrderFactory } from '@0x/contracts-test-utils';
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
-import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
import { SwapQuote, SwapQuoteConsumer } from '../src';
-import { ExtensionContractType } from '../src/types';
+import { constants } from '../src/constants';
+import { ExtensionContractType, MarketOperation, PrunedSignedOrder } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { migrateOnceAsync } from './utils/migrate';
-import { getFullyFillableSwapQuoteWithNoFees, getSignedOrdersWithNoFeesAsync } from './utils/swap_quote';
+import { getFullyFillableSwapQuoteWithNoFees } from './utils/swap_quote';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
@@ -19,15 +22,52 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000);
const TESTRPC_CHAIN_ID = 1337;
-const FILLABLE_AMOUNTS = [new BigNumber(2), new BigNumber(3), new BigNumber(5)].map(value =>
- value.multipliedBy(ONE_ETH_IN_WEI),
-);
-const LARGE_FILLABLE_AMOUNTS = [new BigNumber(20), new BigNumber(20), new BigNumber(20)].map(value =>
- value.multipliedBy(ONE_ETH_IN_WEI),
-);
+const GAS_PRICE = new BigNumber(devConstants.DEFAULT_GAS_PRICE);
+
+const PARTIAL_PRUNED_SIGNED_ORDERS: Array> = [
+ {
+ takerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI),
+ },
+ {
+ takerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(3).multipliedBy(ONE_ETH_IN_WEI),
+ },
+ {
+ takerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(5).multipliedBy(ONE_ETH_IN_WEI),
+ },
+];
+
+const PARTIAL_LARGE_PRUNED_SIGNED_ORDERS: Array> = [
+ {
+ takerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ },
+ {
+ takerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ },
+ {
+ takerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ makerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ fillableTakerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ fillableMakerAssetAmount: new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI),
+ },
+];
describe('swapQuoteConsumerUtils', () => {
- let contractWrappers: ContractWrappers;
+ let wethContract: WETH9Contract;
let userAddresses: string[];
let makerAddress: string;
let takerAddress: string;
@@ -38,25 +78,48 @@ describe('swapQuoteConsumerUtils', () => {
let wethAssetData: string;
let contractAddresses: ContractAddresses;
let swapQuoteConsumer: SwapQuoteConsumer;
+ let orderFactory: OrderFactory;
+ let forwarderOrderFactory: OrderFactory;
const chainId = TESTRPC_CHAIN_ID;
before(async () => {
contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
- const config = {
- chainId,
- contractAddresses,
- };
- contractWrappers = new ContractWrappers(provider, config);
+ const devUtils = new DevUtilsContract(contractAddresses.devUtils, provider);
+ wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
[takerAddress, makerAddress] = userAddresses;
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
[makerAssetData, takerAssetData, wethAssetData] = [
- await contractWrappers.devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
- await contractWrappers.devUtils.encodeERC20AssetData(takerTokenAddress).callAsync(),
- await contractWrappers.devUtils.encodeERC20AssetData(contractAddresses.etherToken).callAsync(),
+ await devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
+ await devUtils.encodeERC20AssetData(takerTokenAddress).callAsync(),
+ await devUtils.encodeERC20AssetData(contractAddresses.etherToken).callAsync(),
];
+ const defaultOrderParams = {
+ ...devConstants.STATIC_ORDER_PARAMS,
+ makerAddress,
+ takerAddress: constants.NULL_ADDRESS,
+ makerAssetData,
+ takerAssetData,
+ makerFeeAssetData: constants.NULL_ERC20_ASSET_DATA,
+ takerFeeAssetData: constants.NULL_ERC20_ASSET_DATA,
+ makerFee: constants.ZERO_AMOUNT,
+ takerFee: constants.ZERO_AMOUNT,
+ feeRecipientAddress: constants.NULL_ADDRESS,
+ exchangeAddress: contractAddresses.exchange,
+ chainId,
+ };
+ const defaultForwarderOrderParams = {
+ ...defaultOrderParams,
+ ...{
+ takerAssetData: wethAssetData,
+ },
+ };
+ const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
+ orderFactory = new OrderFactory(privateKey, defaultOrderParams);
+ forwarderOrderFactory = new OrderFactory(privateKey, defaultForwarderOrderParams);
+
swapQuoteConsumer = new SwapQuoteConsumer(provider, {
chainId,
});
@@ -72,46 +135,50 @@ describe('swapQuoteConsumerUtils', () => {
});
describe('getConsumerTypeForSwapQuoteAsync', () => {
- let forwarderOrders: SignedOrder[];
- let exchangeOrders: SignedOrder[];
- let largeForwarderOrders: SignedOrder[];
+ let forwarderOrders: PrunedSignedOrder[];
+ let exchangeOrders: PrunedSignedOrder[];
+ let largeForwarderOrders: PrunedSignedOrder[];
let forwarderSwapQuote: SwapQuote;
let exchangeSwapQuote: SwapQuote;
let largeForwarderSwapQuote: SwapQuote;
beforeEach(async () => {
- exchangeOrders = await getSignedOrdersWithNoFeesAsync(
- provider,
- makerAssetData,
- takerAssetData,
- makerAddress,
- takerAddress,
- FILLABLE_AMOUNTS,
- );
+ exchangeOrders = [];
+ for (const partialOrder of PARTIAL_PRUNED_SIGNED_ORDERS) {
+ const order = await orderFactory.newSignedOrderAsync(partialOrder);
+ const prunedOrder = {
+ ...order,
+ ...partialOrder,
+ };
+ exchangeOrders.push(prunedOrder as PrunedSignedOrder);
+ }
- forwarderOrders = await getSignedOrdersWithNoFeesAsync(
- provider,
- makerAssetData,
- wethAssetData,
- makerAddress,
- takerAddress,
- FILLABLE_AMOUNTS,
- );
+ forwarderOrders = [];
+ for (const partialOrder of PARTIAL_PRUNED_SIGNED_ORDERS) {
+ const order = await forwarderOrderFactory.newSignedOrderAsync(partialOrder);
+ const prunedOrder = {
+ ...order,
+ ...partialOrder,
+ };
+ forwarderOrders.push(prunedOrder as PrunedSignedOrder);
+ }
- largeForwarderOrders = await getSignedOrdersWithNoFeesAsync(
- provider,
- makerAssetData,
- wethAssetData,
- makerAddress,
- takerAddress,
- LARGE_FILLABLE_AMOUNTS,
- );
+ largeForwarderOrders = [];
+ for (const partialOrder of PARTIAL_LARGE_PRUNED_SIGNED_ORDERS) {
+ const order = await forwarderOrderFactory.newSignedOrderAsync(partialOrder);
+ const prunedOrder = {
+ ...order,
+ ...partialOrder,
+ };
+ largeForwarderOrders.push(prunedOrder as PrunedSignedOrder);
+ }
forwarderSwapQuote = getFullyFillableSwapQuoteWithNoFees(
makerAssetData,
wethAssetData,
forwarderOrders,
MarketOperation.Sell,
+ GAS_PRICE,
);
largeForwarderSwapQuote = getFullyFillableSwapQuoteWithNoFees(
@@ -119,6 +186,7 @@ describe('swapQuoteConsumerUtils', () => {
wethAssetData,
largeForwarderOrders,
MarketOperation.Sell,
+ GAS_PRICE,
);
exchangeSwapQuote = getFullyFillableSwapQuoteWithNoFees(
@@ -126,6 +194,7 @@ describe('swapQuoteConsumerUtils', () => {
takerAssetData,
exchangeOrders,
MarketOperation.Sell,
+ GAS_PRICE,
);
});
@@ -145,7 +214,7 @@ describe('swapQuoteConsumerUtils', () => {
});
it('should return exchange consumer if takerAsset is wEth and taker has enough weth', async () => {
const etherInWei = new BigNumber(20).multipliedBy(ONE_ETH_IN_WEI);
- await contractWrappers.weth9.deposit().sendTransactionAsync({ value: etherInWei, from: takerAddress });
+ await wethContract.deposit().sendTransactionAsync({ value: etherInWei, from: takerAddress });
const extensionContractType = await swapQuoteConsumer.getOptimalExtensionContractTypeAsync(
forwarderSwapQuote,
{ takerAddress },
@@ -154,7 +223,7 @@ describe('swapQuoteConsumerUtils', () => {
});
it('should return forwarder consumer if takerAsset is wEth and takerAddress has no available balance in either weth or eth (defaulting behavior)', async () => {
const etherInWei = new BigNumber(50).multipliedBy(ONE_ETH_IN_WEI);
- await contractWrappers.weth9.deposit().sendTransactionAsync({ value: etherInWei, from: takerAddress });
+ await wethContract.deposit().sendTransactionAsync({ value: etherInWei, from: takerAddress });
const extensionContractType = await swapQuoteConsumer.getOptimalExtensionContractTypeAsync(
largeForwarderSwapQuote,
{ takerAddress },
diff --git a/packages/asset-swapper/test/swap_quoter_test.ts b/packages/asset-swapper/test/swap_quoter_test.ts
index 8f3b4cd6c5..69f935c861 100644
--- a/packages/asset-swapper/test/swap_quoter_test.ts
+++ b/packages/asset-swapper/test/swap_quoter_test.ts
@@ -1,19 +1,19 @@
-import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
import { Orderbook } from '@0x/orderbook';
import { Web3ProviderEngine } from '@0x/subproviders';
import { AssetPairsItem, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai';
import 'mocha';
import * as TypeMoq from 'typemoq';
import { SwapQuoter } from '../src';
import { constants } from '../src/constants';
-import { LiquidityForAssetData, OrdersAndFillableAmounts } from '../src/types';
+import { LiquidityForTakerMakerAssetDataPair, PrunedSignedOrder } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
-import { mockAvailableAssetDatas, mockedSwapQuoterWithOrdersAndFillableAmounts, orderbookMock } from './utils/mocks';
+import { mockAvailableAssetDatas, mockedSwapQuoterWithPrunedSignedOrders, orderbookMock } from './utils/mocks';
+import { testOrderFactory } from './utils/test_order_factory';
+import { baseUnitAmount } from './utils/utils';
chaiSetup.configure();
const expect = chai.expect;
@@ -27,10 +27,6 @@ const WETH_ASSET_DATA = '0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5
const WETH_DECIMALS = constants.ETHER_TOKEN_DECIMALS;
const ZERO = new BigNumber(0);
-const baseUnitAmount = (unitAmount: number, decimals = TOKEN_DECIMALS): BigNumber => {
- return Web3Wrapper.toBaseUnitAmount(new BigNumber(unitAmount), decimals);
-};
-
const assetsToAssetPairItems = (makerAssetData: string, takerAssetData: string): AssetPairsItem[] => {
const defaultAssetPairItem = {
minAmount: ZERO,
@@ -64,15 +60,15 @@ const assetsToAssetPairItems = (makerAssetData: string, takerAssetData: string):
const expectLiquidityResult = async (
web3Provider: Web3ProviderEngine,
orderbook: Orderbook,
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- expectedLiquidityResult: LiquidityForAssetData,
+ prunedOrders: PrunedSignedOrder[],
+ expectedLiquidityResult: LiquidityForTakerMakerAssetDataPair,
) => {
- const mockedSwapQuoter = mockedSwapQuoterWithOrdersAndFillableAmounts(
+ const mockedSwapQuoter = mockedSwapQuoterWithPrunedSignedOrders(
web3Provider,
orderbook,
FAKE_MAKER_ASSET_DATA,
WETH_ASSET_DATA,
- ordersAndFillableAmounts,
+ prunedOrders,
);
const liquidityResult = await mockedSwapQuoter.object.getLiquidityForMakerTakerAssetDataPairAsync(
FAKE_MAKER_ASSET_DATA,
@@ -130,8 +126,8 @@ describe('SwapQuoter', () => {
FAKE_TAKER_ASSET_DATA,
);
expect(liquidityResult).to.deep.equal({
- makerTokensAvailableInBaseUnits: new BigNumber(0),
- takerTokensAvailableInBaseUnits: new BigNumber(0),
+ makerAssetAvailableInBaseUnits: new BigNumber(0),
+ takerAssetAvailableInBaseUnits: new BigNumber(0),
});
});
@@ -144,20 +140,15 @@ describe('SwapQuoter', () => {
FAKE_TAKER_ASSET_DATA,
);
expect(liquidityResult).to.deep.equal({
- makerTokensAvailableInBaseUnits: new BigNumber(0),
- takerTokensAvailableInBaseUnits: new BigNumber(0),
+ makerAssetAvailableInBaseUnits: new BigNumber(0),
+ takerAssetAvailableInBaseUnits: new BigNumber(0),
});
});
});
describe('assetData is supported', () => {
// orders
- const sellTwoTokensFor1Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({
- makerAssetAmount: baseUnitAmount(2),
- takerAssetAmount: baseUnitAmount(1, WETH_DECIMALS),
- chainId: 42,
- });
- const sellTenTokensFor10Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({
+ const sellTenTokensFor10Weth: SignedOrder = testOrderFactory.generateTestSignedOrder({
makerAssetAmount: baseUnitAmount(10),
takerAssetAmount: baseUnitAmount(10, WETH_DECIMALS),
chainId: 42,
@@ -168,98 +159,145 @@ describe('SwapQuoter', () => {
});
it('should return 0s when no orders available', async () => {
- const ordersAndFillableAmounts: OrdersAndFillableAmounts = {
- orders: [],
- remainingFillableMakerAssetAmounts: [],
- };
+ const prunedOrders: PrunedSignedOrder[] = [];
const expectedResult = {
- makerTokensAvailableInBaseUnits: new BigNumber(0),
- takerTokensAvailableInBaseUnits: new BigNumber(0),
+ makerAssetAvailableInBaseUnits: new BigNumber(0),
+ takerAssetAvailableInBaseUnits: new BigNumber(0),
};
await expectLiquidityResult(
mockWeb3Provider.object,
mockOrderbook.object,
- ordersAndFillableAmounts,
+ prunedOrders,
expectedResult,
);
});
it('should return correct computed value when orders provided with full fillableAmounts', async () => {
- const orders: SignedOrder[] = [sellTwoTokensFor1Weth, sellTenTokensFor10Weth];
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1Weth, sellTenTokensFor10Weth],
- remainingFillableMakerAssetAmounts: orders.map(o => o.makerAssetAmount),
- };
-
- const expectedMakerTokensAvailable = orders[0].makerAssetAmount.plus(orders[1].makerAssetAmount);
- const expectedTakerTokensAvailable = orders[0].takerAssetAmount.plus(orders[1].takerAssetAmount);
+ const prunedOrders: PrunedSignedOrder[] = [
+ {
+ ...sellTenTokensFor10Weth,
+ ...{
+ fillableMakerAssetAmount: sellTenTokensFor10Weth.makerAssetAmount,
+ fillableTakerAssetAmount: sellTenTokensFor10Weth.takerAssetAmount,
+ fillableTakerFeeAmount: constants.ZERO_AMOUNT,
+ },
+ },
+ {
+ ...sellTenTokensFor10Weth,
+ ...{
+ fillableMakerAssetAmount: sellTenTokensFor10Weth.makerAssetAmount,
+ fillableTakerAssetAmount: sellTenTokensFor10Weth.takerAssetAmount,
+ fillableTakerFeeAmount: constants.ZERO_AMOUNT,
+ },
+ },
+ ];
+ const expectedMakerAssetAvailable = prunedOrders[0].makerAssetAmount.plus(
+ prunedOrders[1].makerAssetAmount,
+ );
+ const expectedTakerAssetAvailable = prunedOrders[0].takerAssetAmount.plus(
+ prunedOrders[1].takerAssetAmount,
+ );
const expectedResult = {
- makerTokensAvailableInBaseUnits: expectedMakerTokensAvailable,
- takerTokensAvailableInBaseUnits: expectedTakerTokensAvailable,
+ makerAssetAvailableInBaseUnits: expectedMakerAssetAvailable,
+ takerAssetAvailableInBaseUnits: expectedTakerAssetAvailable,
};
await expectLiquidityResult(
mockWeb3Provider.object,
mockOrderbook.object,
- ordersAndFillableAmounts,
+ prunedOrders,
expectedResult,
);
});
it('should return correct computed value with one partial fillableAmounts', async () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1Weth],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(1)],
- };
+ const prunedOrders: PrunedSignedOrder[] = [
+ {
+ ...sellTenTokensFor10Weth,
+ ...{
+ fillableMakerAssetAmount: baseUnitAmount(1),
+ fillableTakerAssetAmount: baseUnitAmount(0.5, WETH_DECIMALS),
+ fillableTakerFeeAmount: constants.ZERO_AMOUNT,
+ },
+ },
+ ];
const expectedResult = {
- makerTokensAvailableInBaseUnits: baseUnitAmount(1),
- takerTokensAvailableInBaseUnits: baseUnitAmount(0.5, WETH_DECIMALS),
+ makerAssetAvailableInBaseUnits: baseUnitAmount(1),
+ takerAssetAvailableInBaseUnits: baseUnitAmount(0.5, WETH_DECIMALS),
};
await expectLiquidityResult(
mockWeb3Provider.object,
mockOrderbook.object,
- ordersAndFillableAmounts,
+ prunedOrders,
expectedResult,
);
});
it('should return correct computed value with multiple orders and fillable amounts', async () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1Weth, sellTenTokensFor10Weth],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(1), baseUnitAmount(3)],
- };
+ const prunedOrders: PrunedSignedOrder[] = [
+ {
+ ...sellTenTokensFor10Weth,
+ ...{
+ fillableMakerAssetAmount: baseUnitAmount(1),
+ fillableTakerAssetAmount: baseUnitAmount(0.5, WETH_DECIMALS),
+ fillableTakerFeeAmount: constants.ZERO_AMOUNT,
+ },
+ },
+ {
+ ...sellTenTokensFor10Weth,
+ ...{
+ fillableMakerAssetAmount: baseUnitAmount(3),
+ fillableTakerAssetAmount: baseUnitAmount(3, WETH_DECIMALS),
+ fillableTakerFeeAmount: constants.ZERO_AMOUNT,
+ },
+ },
+ ];
const expectedResult = {
- makerTokensAvailableInBaseUnits: baseUnitAmount(4),
- takerTokensAvailableInBaseUnits: baseUnitAmount(3.5, WETH_DECIMALS),
+ makerAssetAvailableInBaseUnits: baseUnitAmount(4),
+ takerAssetAvailableInBaseUnits: baseUnitAmount(3.5, WETH_DECIMALS),
};
await expectLiquidityResult(
mockWeb3Provider.object,
mockOrderbook.object,
- ordersAndFillableAmounts,
+ prunedOrders,
expectedResult,
);
});
it('should return 0s when no amounts fillable', async () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1Weth, sellTenTokensFor10Weth],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(0), baseUnitAmount(0)],
- };
+ const prunedOrders: PrunedSignedOrder[] = [
+ {
+ ...sellTenTokensFor10Weth,
+ ...{
+ fillableMakerAssetAmount: constants.ZERO_AMOUNT,
+ fillableTakerAssetAmount: constants.ZERO_AMOUNT,
+ fillableTakerFeeAmount: constants.ZERO_AMOUNT,
+ },
+ },
+ {
+ ...sellTenTokensFor10Weth,
+ ...{
+ fillableMakerAssetAmount: constants.ZERO_AMOUNT,
+ fillableTakerAssetAmount: constants.ZERO_AMOUNT,
+ fillableTakerFeeAmount: constants.ZERO_AMOUNT,
+ },
+ },
+ ];
const expectedResult = {
- makerTokensAvailableInBaseUnits: baseUnitAmount(0),
- takerTokensAvailableInBaseUnits: baseUnitAmount(0, WETH_DECIMALS),
+ makerAssetAvailableInBaseUnits: constants.ZERO_AMOUNT,
+ takerAssetAvailableInBaseUnits: constants.ZERO_AMOUNT,
};
await expectLiquidityResult(
mockWeb3Provider.object,
mockOrderbook.object,
- ordersAndFillableAmounts,
+ prunedOrders,
expectedResult,
);
});
diff --git a/packages/asset-swapper/test/utils/consumer_utils.ts b/packages/asset-swapper/test/utils/consumer_utils.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/asset-swapper/test/utils/mocks.ts b/packages/asset-swapper/test/utils/mocks.ts
index 482be06634..6aa6ec724f 100644
--- a/packages/asset-swapper/test/utils/mocks.ts
+++ b/packages/asset-swapper/test/utils/mocks.ts
@@ -4,7 +4,7 @@ import { APIOrder, AssetPairsItem, SignedOrder } from '@0x/types';
import * as TypeMoq from 'typemoq';
import { SwapQuoter } from '../../src/swap_quoter';
-import { OrdersAndFillableAmounts } from '../../src/types';
+import { PrunedSignedOrder } from '../../src/types';
class OrderbookClass extends Orderbook {
// tslint:disable-next-line:prefer-function-over-method
@@ -49,26 +49,26 @@ const partiallyMockedSwapQuoter = (provider: Web3ProviderEngine, orderbook: Orde
return mockedSwapQuoter;
};
-const mockGetOrdersAndAvailableAmounts = (
+const mockGetPrunedSignedOrdersAsync = (
mockedSwapQuoter: TypeMoq.IMock,
makerAssetData: string,
takerAssetData: string,
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
+ prunedOrders: PrunedSignedOrder[],
): void => {
mockedSwapQuoter
- .setup(async a => a.getOrdersAndFillableAmountsAsync(makerAssetData, takerAssetData))
- .returns(async () => Promise.resolve(ordersAndFillableAmounts))
+ .setup(async a => a.getPrunedSignedOrdersAsync(makerAssetData, takerAssetData))
+ .returns(async () => Promise.resolve(prunedOrders))
.verifiable(TypeMoq.Times.once());
};
-export const mockedSwapQuoterWithOrdersAndFillableAmounts = (
+export const mockedSwapQuoterWithPrunedSignedOrders = (
provider: Web3ProviderEngine,
orderbook: Orderbook,
makerAssetData: string,
takerAssetData: string,
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
+ prunedOrders: PrunedSignedOrder[],
): TypeMoq.IMock => {
const mockedAssetQuoter = partiallyMockedSwapQuoter(provider, orderbook);
- mockGetOrdersAndAvailableAmounts(mockedAssetQuoter, makerAssetData, takerAssetData, ordersAndFillableAmounts);
+ mockGetPrunedSignedOrdersAsync(mockedAssetQuoter, makerAssetData, takerAssetData, prunedOrders);
return mockedAssetQuoter;
};
diff --git a/packages/asset-swapper/test/utils/swap_quote.ts b/packages/asset-swapper/test/utils/swap_quote.ts
index 46bc8b0e2f..1aab941a95 100644
--- a/packages/asset-swapper/test/utils/swap_quote.ts
+++ b/packages/asset-swapper/test/utils/swap_quote.ts
@@ -1,134 +1,40 @@
-import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
-import { MarketOperation, SignedOrder } from '@0x/types';
+import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
-import { SupportedProvider } from '@0x/web3-wrapper';
import * as _ from 'lodash';
import { constants } from '../../src/constants';
-import { SwapQuote } from '../../src/types';
-
-const ZERO_BIG_NUMBER = new BigNumber(0);
-
-export const getSignedOrdersWithNoFeesAsync = async (
- provider: SupportedProvider,
- makerAssetData: string,
- takerAssetData: string,
- makerAddress: string,
- takerAddress: string,
- fillableAmounts: BigNumber[],
- exchangeAddress?: string,
-): Promise => {
- const promises = _.map(fillableAmounts, async (fillableAmount: BigNumber) =>
- orderFactory.createSignedOrderAsync(
- provider,
- makerAddress,
- fillableAmount,
- makerAssetData,
- fillableAmount,
- takerAssetData,
- exchangeAddress || constants.NULL_ADDRESS,
- ),
- );
- return Promise.all(promises);
-};
-
-export const getPartialSignedOrdersWithNoFees = (
- makerAssetData: string,
- takerAssetData: string,
- makerAddress: string,
- takerAddress: string,
- fillableAmounts: BigNumber[],
-): SignedOrder[] => {
- return _.map(fillableAmounts, (fillableAmount: BigNumber) =>
- orderFactory.createSignedOrderFromPartial({
- makerAddress,
- makerAssetAmount: fillableAmount,
- makerAssetData,
- takerAssetAmount: fillableAmount,
- takerAssetData,
- chainId: 42,
- }),
- );
-};
-
-export const getPartialSignedOrdersWithFees = (
- makerAssetData: string,
- takerAssetData: string,
- makerAddress: string,
- takerAddress: string,
- fillableAmounts: BigNumber[],
- takerFees: BigNumber[],
-): SignedOrder[] => {
- const orders = getPartialSignedOrdersWithNoFees(
- makerAssetData,
- takerAssetData,
- makerAddress,
- takerAddress,
- fillableAmounts,
- );
- return _.map(orders, (order: SignedOrder, index: number) =>
- orderFactory.createSignedOrderFromPartial({
- ...order,
- ...{ takerFee: takerFees[index] },
- chainId: 42,
- }),
- );
-};
-
-export const getFullyFillableSwapQuoteWithFees = (
- makerAssetData: string,
- takerAssetData: string,
- orders: SignedOrder[],
- feeOrders: SignedOrder[],
- operation: MarketOperation,
-) => {
- const swapQuote = getFullyFillableSwapQuoteWithNoFees(makerAssetData, takerAssetData, orders, operation);
- swapQuote.feeOrders = feeOrders;
- const totalFeeTakerTokenAmount = _.reduce(
- feeOrders,
- (a: BigNumber, c: SignedOrder) => a.plus(c.takerAssetAmount),
- ZERO_BIG_NUMBER,
- );
- // Adds fees to the SwapQuoteInfos assuming all feeOrders will be filled
- swapQuote.bestCaseQuoteInfo.feeTakerTokenAmount = totalFeeTakerTokenAmount;
- swapQuote.worstCaseQuoteInfo.feeTakerTokenAmount = totalFeeTakerTokenAmount;
- swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount = swapQuote.bestCaseQuoteInfo.totalTakerTokenAmount.plus(
- totalFeeTakerTokenAmount,
- );
- swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount = swapQuote.worstCaseQuoteInfo.totalTakerTokenAmount.plus(
- totalFeeTakerTokenAmount,
- );
- return swapQuote;
-};
+import { MarketOperation, PrunedSignedOrder, SwapQuote } from '../../src/types';
+import { protocolFeeUtils } from '../../src/utils/protocol_fee_utils';
export const getFullyFillableSwapQuoteWithNoFees = (
makerAssetData: string,
takerAssetData: string,
- orders: SignedOrder[],
+ orders: PrunedSignedOrder[],
operation: MarketOperation,
+ gasPrice: BigNumber,
): SwapQuote => {
const makerAssetFillAmount = _.reduce(
orders,
(a: BigNumber, c: SignedOrder) => a.plus(c.makerAssetAmount),
- ZERO_BIG_NUMBER,
+ constants.ZERO_AMOUNT,
);
- const totalTakerTokenAmount = _.reduce(
+ const totalTakerAssetAmount = _.reduce(
orders,
(a: BigNumber, c: SignedOrder) => a.plus(c.takerAssetAmount),
- ZERO_BIG_NUMBER,
+ constants.ZERO_AMOUNT,
);
const quoteInfo = {
- makerTokenAmount: makerAssetFillAmount,
- takerTokenAmount: totalTakerTokenAmount,
- feeTakerTokenAmount: ZERO_BIG_NUMBER,
- totalTakerTokenAmount,
+ makerAssetAmount: makerAssetFillAmount,
+ feeTakerAssetAmount: constants.ZERO_AMOUNT,
+ takerAssetAmount: totalTakerAssetAmount,
+ totalTakerAssetAmount,
+ protocolFeeInEthAmount: protocolFeeUtils.calculateWorstCaseProtocolFee(orders, gasPrice),
};
const quoteBase = {
makerAssetData,
takerAssetData,
orders,
- feeOrders: [],
bestCaseQuoteInfo: quoteInfo,
worstCaseQuoteInfo: quoteInfo,
};
@@ -143,7 +49,7 @@ export const getFullyFillableSwapQuoteWithNoFees = (
return {
...quoteBase,
type: MarketOperation.Sell,
- takerAssetFillAmount: totalTakerTokenAmount,
+ takerAssetFillAmount: totalTakerAssetAmount,
};
}
};
diff --git a/packages/asset-swapper/test/utils/test_order_factory.ts b/packages/asset-swapper/test/utils/test_order_factory.ts
new file mode 100644
index 0000000000..96c3881d0d
--- /dev/null
+++ b/packages/asset-swapper/test/utils/test_order_factory.ts
@@ -0,0 +1,63 @@
+import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
+import { Order, SignedOrder } from '@0x/types';
+import * as _ from 'lodash';
+
+import { constants } from '../../src/constants';
+import { PrunedSignedOrder } from '../../src/types';
+
+const CHAIN_ID = 1337;
+const BASE_TEST_ORDER: Order = orderFactory.createOrder(
+ constants.NULL_ADDRESS,
+ constants.ZERO_AMOUNT,
+ constants.NULL_ERC20_ASSET_DATA,
+ constants.ZERO_AMOUNT,
+ constants.NULL_ERC20_ASSET_DATA,
+ constants.NULL_ADDRESS,
+ CHAIN_ID,
+);
+
+const BASE_TEST_SIGNED_ORDER: SignedOrder = {
+ ...BASE_TEST_ORDER,
+ signature: constants.NULL_BYTES,
+};
+
+const BASE_TEST_PRUNED_SIGNED_ORDER: PrunedSignedOrder = {
+ ...BASE_TEST_SIGNED_ORDER,
+ fillableMakerAssetAmount: constants.ZERO_AMOUNT,
+ fillableTakerAssetAmount: constants.ZERO_AMOUNT,
+ fillableTakerFeeAmount: constants.ZERO_AMOUNT,
+};
+
+export const testOrderFactory = {
+ generateTestSignedOrder(partialOrder: Partial): SignedOrder {
+ return transformObject(BASE_TEST_SIGNED_ORDER, partialOrder);
+ },
+ generateIdenticalTestSignedOrders(partialOrder: Partial, numOrders: number): SignedOrder[] {
+ const baseTestOrders = _.map(_.range(numOrders), () => BASE_TEST_SIGNED_ORDER);
+ return _.map(baseTestOrders, order => transformObject(order, partialOrder));
+ },
+ generateTestSignedOrders(partialOrders: Array>): SignedOrder[] {
+ return _.map(partialOrders, partialOrder => transformObject(BASE_TEST_SIGNED_ORDER, partialOrder));
+ },
+ generateTestPrunedSignedOrder(partialOrder: Partial): PrunedSignedOrder {
+ return transformObject(BASE_TEST_PRUNED_SIGNED_ORDER, partialOrder);
+ },
+ generateIdenticalTestPrunedSignedOrders(
+ partialOrder: Partial,
+ numOrders: number,
+ ): PrunedSignedOrder[] {
+ const baseTestOrders = _.map(_.range(numOrders), () => BASE_TEST_PRUNED_SIGNED_ORDER);
+ return _.map(baseTestOrders, (baseOrder): PrunedSignedOrder => transformObject(baseOrder, partialOrder));
+ },
+ generateTestPrunedSignedOrders(partialOrders: Array>): PrunedSignedOrder[] {
+ return _.map(
+ partialOrders,
+ (partialOrder): PrunedSignedOrder => transformObject(BASE_TEST_PRUNED_SIGNED_ORDER, partialOrder),
+ );
+ },
+};
+
+function transformObject(input: T, transformation: Partial): T {
+ const copy = _.cloneDeep(input);
+ return _.assign(copy, transformation);
+}
diff --git a/packages/asset-swapper/test/utils/test_orders.ts b/packages/asset-swapper/test/utils/test_orders.ts
new file mode 100644
index 0000000000..0dbbbba579
--- /dev/null
+++ b/packages/asset-swapper/test/utils/test_orders.ts
@@ -0,0 +1,146 @@
+import { PrunedSignedOrder } from '../../src/types';
+
+import { testOrderFactory } from './test_order_factory';
+import { baseUnitAmount } from './utils';
+
+// tslint:disable:custom-no-magic-numbers
+
+const FAKE_ERC20_TAKER_ASSET_DATA = '0xf47261b22222222222222222222222222222222222222222222222222222222222222222';
+const FAKE_ERC20_MAKER_ASSET_DATA = '0xf47261b11111111111111111111111111111111111111111111111111111111111111111';
+
+const PARTIAL_ORDER: Partial = {
+ takerAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ makerAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+};
+
+const PARTIAL_ORDER_FEE_IN_TAKER_ASSET: Partial = {
+ ...{
+ takerFeeAssetData: FAKE_ERC20_TAKER_ASSET_DATA,
+ },
+ ...PARTIAL_ORDER,
+};
+
+const PARTIAL_ORDER_FEE_IN_MAKER_ASSET: Partial = {
+ ...{
+ takerFeeAssetData: FAKE_ERC20_MAKER_ASSET_DATA,
+ },
+ ...PARTIAL_ORDER,
+};
+
+const PARTIAL_PRUNED_SIGNED_ORDERS_FEELESS: Array> = [
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(1),
+ makerAssetAmount: baseUnitAmount(6),
+ fillableTakerAssetAmount: baseUnitAmount(1),
+ fillableMakerAssetAmount: baseUnitAmount(6),
+ },
+ ...PARTIAL_ORDER,
+ },
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(10),
+ makerAssetAmount: baseUnitAmount(4),
+ fillableTakerAssetAmount: baseUnitAmount(5),
+ fillableMakerAssetAmount: baseUnitAmount(2),
+ },
+ ...PARTIAL_ORDER,
+ },
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(6),
+ makerAssetAmount: baseUnitAmount(6),
+ fillableTakerAssetAmount: baseUnitAmount(3),
+ fillableMakerAssetAmount: baseUnitAmount(2),
+ },
+ ...PARTIAL_ORDER,
+ },
+];
+
+const PARTIAL_PRUNED_SIGNED_FEE_IN_TAKER_ASSET: Array> = [
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(1),
+ makerAssetAmount: baseUnitAmount(6),
+ takerFee: baseUnitAmount(3),
+ fillableTakerAssetAmount: baseUnitAmount(1),
+ fillableMakerAssetAmount: baseUnitAmount(6),
+ fillableTakerFeeAmount: baseUnitAmount(3),
+ },
+ ...PARTIAL_ORDER_FEE_IN_TAKER_ASSET,
+ },
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(10),
+ makerAssetAmount: baseUnitAmount(4),
+ takerFee: baseUnitAmount(2),
+ fillableTakerAssetAmount: baseUnitAmount(5),
+ fillableMakerAssetAmount: baseUnitAmount(2),
+ fillableTakerFeeAmount: baseUnitAmount(1),
+ },
+ ...PARTIAL_ORDER_FEE_IN_TAKER_ASSET,
+ },
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(6),
+ makerAssetAmount: baseUnitAmount(6),
+ takerFee: baseUnitAmount(4),
+ fillableTakerAssetAmount: baseUnitAmount(3),
+ fillableMakerAssetAmount: baseUnitAmount(2),
+ fillableTakerFeeAmount: baseUnitAmount(2),
+ },
+ ...PARTIAL_ORDER_FEE_IN_TAKER_ASSET,
+ },
+];
+
+const PARTIAL_PRUNED_SIGNED_FEE_IN_MAKER_ASSET: Array> = [
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(5),
+ makerAssetAmount: baseUnitAmount(2),
+ takerFee: baseUnitAmount(1),
+ fillableTakerAssetAmount: baseUnitAmount(5),
+ fillableMakerAssetAmount: baseUnitAmount(2),
+ fillableTakerFeeAmount: baseUnitAmount(1),
+ },
+ ...PARTIAL_ORDER_FEE_IN_MAKER_ASSET,
+ },
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(2),
+ makerAssetAmount: baseUnitAmount(12),
+ takerFee: baseUnitAmount(6),
+ fillableTakerAssetAmount: baseUnitAmount(1),
+ fillableMakerAssetAmount: baseUnitAmount(6),
+ fillableTakerFeeAmount: baseUnitAmount(3),
+ },
+ ...PARTIAL_ORDER_FEE_IN_MAKER_ASSET,
+ },
+ {
+ ...{
+ takerAssetAmount: baseUnitAmount(3),
+ makerAssetAmount: baseUnitAmount(3),
+ takerFee: baseUnitAmount(2),
+ fillableTakerAssetAmount: baseUnitAmount(3),
+ fillableMakerAssetAmount: baseUnitAmount(3),
+ fillableTakerFeeAmount: baseUnitAmount(2),
+ },
+ ...PARTIAL_ORDER_FEE_IN_MAKER_ASSET,
+ },
+];
+
+const PRUNED_SIGNED_ORDERS_FEELESS = testOrderFactory.generateTestPrunedSignedOrders(
+ PARTIAL_PRUNED_SIGNED_ORDERS_FEELESS,
+);
+const PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET = testOrderFactory.generateTestPrunedSignedOrders(
+ PARTIAL_PRUNED_SIGNED_FEE_IN_TAKER_ASSET,
+);
+const PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET = testOrderFactory.generateTestPrunedSignedOrders(
+ PARTIAL_PRUNED_SIGNED_FEE_IN_MAKER_ASSET,
+);
+
+export const testOrders = {
+ PRUNED_SIGNED_ORDERS_FEELESS,
+ PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET,
+ PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET,
+};
diff --git a/packages/asset-swapper/test/utils/utils.ts b/packages/asset-swapper/test/utils/utils.ts
new file mode 100644
index 0000000000..1e01d59f0e
--- /dev/null
+++ b/packages/asset-swapper/test/utils/utils.ts
@@ -0,0 +1,9 @@
+import { BigNumber } from '@0x/utils';
+import { Web3Wrapper } from '@0x/web3-wrapper';
+
+const TOKEN_DECIMALS = 18;
+
+// tslint:disable:custom-no-magic-numbers
+export const baseUnitAmount = (unitAmount: number, decimals = TOKEN_DECIMALS): BigNumber => {
+ return Web3Wrapper.toBaseUnitAmount(new BigNumber(unitAmount), decimals);
+};
diff --git a/packages/asset-swapper/test/utils_test.ts b/packages/asset-swapper/test/utils_test.ts
deleted file mode 100644
index 801ce09761..0000000000
--- a/packages/asset-swapper/test/utils_test.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import * as chai from 'chai';
-import 'mocha';
-
-import { constants } from '../src/constants';
-import { utils } from '../src/utils/utils';
-
-import { chaiSetup } from './utils/chai_setup';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-const TOKEN_DECIMALS = 18;
-const WETH_DECIMALS = constants.ETHER_TOKEN_DECIMALS;
-
-const baseUnitAmount = (unitAmount: number, decimals = TOKEN_DECIMALS): BigNumber => {
- return Web3Wrapper.toBaseUnitAmount(new BigNumber(unitAmount), decimals);
-};
-
-// tslint:disable:custom-no-magic-numbers
-describe('utils', () => {
- // orders
- const sellTwoTokensFor1Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: baseUnitAmount(2),
- takerAssetAmount: baseUnitAmount(1, WETH_DECIMALS),
- });
- const sellTenTokensFor10Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: baseUnitAmount(10),
- takerAssetAmount: baseUnitAmount(10, WETH_DECIMALS),
- });
- const sellTwoTokensFor1WethWithTwoTokenFee: SignedOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: baseUnitAmount(2),
- takerAssetAmount: baseUnitAmount(1, WETH_DECIMALS),
- takerFee: baseUnitAmount(2),
- });
- const sellTenTokensFor1WethWithFourTokenFee: SignedOrder = orderFactory.createSignedOrderFromPartial({
- chainId: 42,
- makerAssetAmount: baseUnitAmount(2),
- takerAssetAmount: baseUnitAmount(1, WETH_DECIMALS),
- takerFee: baseUnitAmount(4),
- });
- describe('isFeeOrdersRequiredToFillOrders', async () => {
- it('should return true if ordersAndFillableAmounts is completed unfilled and has fees', () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1WethWithTwoTokenFee, sellTenTokensFor1WethWithFourTokenFee],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(1), baseUnitAmount(10)],
- };
- const isFeeOrdersRequired = utils.isFeeOrdersRequiredToFillOrders(ordersAndFillableAmounts);
- expect(isFeeOrdersRequired).to.equal(true);
- });
- it('should return true if ordersAndFillableAmounts is partially unfilled and has fees', () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1WethWithTwoTokenFee, sellTenTokensFor1WethWithFourTokenFee],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(0), baseUnitAmount(5)],
- };
- const isFeeOrdersRequired = utils.isFeeOrdersRequiredToFillOrders(ordersAndFillableAmounts);
- expect(isFeeOrdersRequired).to.equal(true);
- });
- it('should return false if ordersAndFillableAmounts is completed filled and has fees', () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1WethWithTwoTokenFee, sellTenTokensFor1WethWithFourTokenFee],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(0), baseUnitAmount(0)],
- };
- const isFeeOrdersRequired = utils.isFeeOrdersRequiredToFillOrders(ordersAndFillableAmounts);
- expect(isFeeOrdersRequired).to.equal(false);
- });
- it("should return false if ordersAndFillableAmounts is completely unfilled and doesn't have fees", () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1Weth, sellTenTokensFor10Weth],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(1), baseUnitAmount(10)],
- };
- const isFeeOrdersRequired = utils.isFeeOrdersRequiredToFillOrders(ordersAndFillableAmounts);
- expect(isFeeOrdersRequired).to.equal(false);
- });
- });
-});
diff --git a/packages/migrations/CHANGELOG.json b/packages/migrations/CHANGELOG.json
index cdff0cfb68..6fe2a90e20 100644
--- a/packages/migrations/CHANGELOG.json
+++ b/packages/migrations/CHANGELOG.json
@@ -16,7 +16,7 @@
},
{
"note": "Deploy Forwarder AFTER staking is hooked up",
- "pr": "TODO"
+ "pr": 2350
}
]
},