aboutsummaryrefslogtreecommitdiffstats
path: root/packages/asset-buyer
diff options
context:
space:
mode:
Diffstat (limited to 'packages/asset-buyer')
-rw-r--r--packages/asset-buyer/.npmignore8
-rw-r--r--packages/asset-buyer/CHANGELOG.json243
-rw-r--r--packages/asset-buyer/CHANGELOG.md94
-rw-r--r--packages/asset-buyer/README.md83
-rw-r--r--packages/asset-buyer/package.json74
-rw-r--r--packages/asset-buyer/src/asset_buyer.ts365
-rw-r--r--packages/asset-buyer/src/constants.ts40
-rw-r--r--packages/asset-buyer/src/errors.ts22
-rw-r--r--packages/asset-buyer/src/globals.d.ts6
-rw-r--r--packages/asset-buyer/src/index.ts29
-rw-r--r--packages/asset-buyer/src/order_providers/basic_order_provider.ts41
-rw-r--r--packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts111
-rw-r--r--packages/asset-buyer/src/types.ts142
-rw-r--r--packages/asset-buyer/src/utils/assert.ts39
-rw-r--r--packages/asset-buyer/src/utils/asset_data_utils.ts12
-rw-r--r--packages/asset-buyer/src/utils/buy_quote_calculator.ts221
-rw-r--r--packages/asset-buyer/src/utils/calculate_liquidity.ts34
-rw-r--r--packages/asset-buyer/src/utils/order_provider_response_processor.ts171
-rw-r--r--packages/asset-buyer/src/utils/order_utils.ts74
-rw-r--r--packages/asset-buyer/test/asset_buyer_test.ts212
-rw-r--r--packages/asset-buyer/test/buy_quote_calculator_test.ts295
-rw-r--r--packages/asset-buyer/test/utils/chai_setup.ts13
-rw-r--r--packages/asset-buyer/test/utils/mocks.ts68
-rw-r--r--packages/asset-buyer/test/utils/test_helpers.ts26
-rw-r--r--packages/asset-buyer/tsconfig.json8
-rw-r--r--packages/asset-buyer/tslint.json3
-rw-r--r--packages/asset-buyer/typedoc-tsconfig.json7
27 files changed, 0 insertions, 2441 deletions
diff --git a/packages/asset-buyer/.npmignore b/packages/asset-buyer/.npmignore
deleted file mode 100644
index 5333847e7..000000000
--- a/packages/asset-buyer/.npmignore
+++ /dev/null
@@ -1,8 +0,0 @@
-.*
-yarn-error.log
-/src/
-/scripts/
-/schemas/
-test/
-tsconfig.json
-/lib/src/monorepo_scripts/
diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json
deleted file mode 100644
index 2de603de0..000000000
--- a/packages/asset-buyer/CHANGELOG.json
+++ /dev/null
@@ -1,243 +0,0 @@
-[
- {
- "version": "5.0.0",
- "changes": [
- {
- "note": "Upgrade the bignumber.js to v8.0.2",
- "pr": 1517
- }
- ]
- },
- {
- "version": "4.1.0",
- "changes": [
- {
- "note": "Adds new public method getLiquidityForAssetDataAsync, and exposes getOrdersAndFillableAmountsAsync as public method",
- "pr": 1512
- }
- ]
- },
- {
- "timestamp": 1547747677,
- "version": "4.0.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1547561734,
- "version": "4.0.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "4.0.0",
- "changes": [
- {
- "note": "Raise custom InsufficientAssetLiquidityError error with amountAvailableToFill attribute",
- "pr": 1437
- }
- ],
- "timestamp": 1547225310
- },
- {
- "timestamp": 1547040760,
- "version": "3.0.5",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "3.0.4",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1544739608
- },
- {
- "version": "3.0.3",
- "changes": [
- {
- "note": "Update SRA order provider to include Dai"
- }
- ],
- "timestamp": 1544570656
- },
- {
- "timestamp": 1543401373,
- "version": "3.0.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "3.0.1",
- "changes": [
- {
- "note": "Dependencies updated",
- "pr": 1276
- }
- ],
- "timestamp": 1542821676
- },
- {
- "version": "3.0.0",
- "changes": [
- {
- "note": "update `getBuyQuoteAsync` to return eth spent on assets instead of per unit amount",
- "pr": 1252
- }
- ],
- "timestamp": 1542208198
- },
- {
- "timestamp": 1542134075,
- "version": "2.2.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542028948,
- "version": "2.2.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "2.2.0",
- "changes": [
- {
- "note": "`getAssetBuyerForProvidedOrders` factory function now takes 3 args instead of 4",
- "pr": 1187
- },
- {
- "note": "the `OrderProvider` now requires a new method `getAvailableMakerAssetDatasAsync` and the `StandardRelayerAPIOrderProvider` requires the network id at init.",
- "pr": 1203
- },
- {
- "note": "No longer require that provided orders all have the same maker and taker asset data",
- "pr": 1197
- },
- {
- "note": "Fix bug where `BuyQuoteInfo` objects could return `totalEthAmount` and `feeEthAmount` that were not whole numbers",
- "pr": 1207
- },
- {
- "note": "Fix bug where default values for `AssetBuyer` public facing methods could get overriden by `undefined` values",
- "pr": 1207
- },
- {
- "note": "Lower default expiry buffer from 5 minutes to 2 minutes",
- "pr": 1217
- }
- ],
- "timestamp": 1541740904
- },
- {
- "version": "2.1.0",
- "changes": [
- {
- "note": "Add `gasLimit` and `gasPrice` as optional properties on `BuyQuoteExecutionOpts`"
- },
- {
- "note": "Export `BuyQuoteInfo` type",
- "pr": 1131
- },
- {
- "note": "Updated to use new modularized artifacts and the latest version of @0xproject/contract-wrappers",
- "pr": 1105
- },
- {
- "note": "Add `gasLimit` and `gasPrice` as optional properties on `BuyQuoteExecutionOpts`",
- "pr": 1116
- },
- {
- "note": "Add `docs:json` command to package.json",
- "pr": 1139
- },
- {
- "note": "Add missing types to public interface",
- "pr": 1139
- },
- {
- "note": "Throw `SignatureRequestDenied` and `TransactionValueTooLow` errors when executing buy",
- "pr": 1147
- }
- ],
- "timestamp": 1539871071
- },
- {
- "version": "2.0.0",
- "changes": [
- {
- "note": "Expand AssetBuyer to work with multiple assets at once",
- "pr": 1086
- },
- {
- "note": "Fix minRate and maxRate calculation",
- "pr": 1113
- }
- ],
- "timestamp": 1538693146
- },
- {
- "timestamp": 1538475601,
- "version": "1.0.3",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1538157789,
- "version": "1.0.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1537907159,
- "version": "1.0.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1537875740,
- "version": "1.0.0",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "1.0.0-rc.1",
- "changes": [
- {
- "note": "Init"
- }
- ]
- }
-]
diff --git a/packages/asset-buyer/CHANGELOG.md b/packages/asset-buyer/CHANGELOG.md
deleted file mode 100644
index f2a3d2236..000000000
--- a/packages/asset-buyer/CHANGELOG.md
+++ /dev/null
@@ -1,94 +0,0 @@
-<!--
-changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
-Edit the package's CHANGELOG.json file only.
--->
-
-CHANGELOG
-
-## v4.0.2 - _January 17, 2019_
-
- * Dependencies updated
-
-## v4.0.1 - _January 15, 2019_
-
- * Dependencies updated
-
-## v4.0.0 - _January 11, 2019_
-
- * Raise custom InsufficientAssetLiquidityError error with amountAvailableToFill attribute (#1437)
-
-## v3.0.5 - _January 9, 2019_
-
- * Dependencies updated
-
-## v3.0.4 - _December 13, 2018_
-
- * Dependencies updated
-
-## v3.0.3 - _December 11, 2018_
-
- * Update SRA order provider to include Dai
-
-## v3.0.2 - _November 28, 2018_
-
- * Dependencies updated
-
-## v3.0.1 - _November 21, 2018_
-
- * Dependencies updated (#1276)
-
-## v3.0.0 - _November 14, 2018_
-
- * update `getBuyQuoteAsync` to return eth spent on assets instead of per unit amount (#1252)
-
-## v2.2.2 - _November 13, 2018_
-
- * Dependencies updated
-
-## v2.2.1 - _November 12, 2018_
-
- * Dependencies updated
-
-## v2.2.0 - _November 9, 2018_
-
- * `getAssetBuyerForProvidedOrders` factory function now takes 3 args instead of 4 (#1187)
- * the `OrderProvider` now requires a new method `getAvailableMakerAssetDatasAsync` and the `StandardRelayerAPIOrderProvider` requires the network id at init. (#1203)
- * No longer require that provided orders all have the same maker and taker asset data (#1197)
- * Fix bug where `BuyQuoteInfo` objects could return `totalEthAmount` and `feeEthAmount` that were not whole numbers (#1207)
- * Fix bug where default values for `AssetBuyer` public facing methods could get overriden by `undefined` values (#1207)
- * Lower default expiry buffer from 5 minutes to 2 minutes (#1217)
-
-## v2.1.0 - _October 18, 2018_
-
- * Add `gasLimit` and `gasPrice` as optional properties on `BuyQuoteExecutionOpts`
- * Export `BuyQuoteInfo` type (#1131)
- * Updated to use new modularized artifacts and the latest version of @0xproject/contract-wrappers (#1105)
- * Add `gasLimit` and `gasPrice` as optional properties on `BuyQuoteExecutionOpts` (#1116)
- * Add `docs:json` command to package.json (#1139)
- * Add missing types to public interface (#1139)
- * Throw `SignatureRequestDenied` and `TransactionValueTooLow` errors when executing buy (#1147)
-
-## v2.0.0 - _October 4, 2018_
-
- * Expand AssetBuyer to work with multiple assets at once (#1086)
- * Fix minRate and maxRate calculation (#1113)
-
-## v1.0.3 - _October 2, 2018_
-
- * Dependencies updated
-
-## v1.0.2 - _September 28, 2018_
-
- * Dependencies updated
-
-## v1.0.1 - _September 25, 2018_
-
- * Dependencies updated
-
-## v1.0.0 - _September 25, 2018_
-
- * Dependencies updated
-
-## v1.0.0-rc.1 - _Invalid date_
-
- * Init
diff --git a/packages/asset-buyer/README.md b/packages/asset-buyer/README.md
deleted file mode 100644
index b854bda11..000000000
--- a/packages/asset-buyer/README.md
+++ /dev/null
@@ -1,83 +0,0 @@
-## @0x/asset-buyer
-
-Convenience package for buying assets represented on the Ethereum blockchain using 0x. In its simplest form, the package helps in the usage of the [0x forwarder contract](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md), which allows users to execute [Wrapped Ether](https://weth.io/) based 0x orders without having to set allowances, wrap Ether or own ZRX, meaning they can buy tokens with Ether alone. Given some liquidity (0x signed orders), it helps estimate the Ether cost of buying a certain asset (giving a range) and then buying that asset.
-
-In its more advanced and useful form, it integrates with the [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) and takes care of sourcing liquidity for you given an SRA compliant endpoint. The final result is a library that tells you what assets are available, provides an Ether based quote for any asset desired, and allows you to buy that asset using Ether alone.
-
-## Installation
-
-```bash
-yarn add @0x/asset-buyer
-```
-
-**Import**
-
-```typescript
-import { AssetBuyer } from '@0x/asset-buyer';
-```
-
-or
-
-```javascript
-var AssetBuyer = require('@0x/asset-buyer').AssetBuyer;
-```
-
-If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
-
-```json
-"compilerOptions": {
- "typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"],
-}
-```
-
-## Contributing
-
-We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
-
-Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
-
-### Install dependencies
-
-If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
-
-```bash
-yarn config set workspaces-experimental true
-```
-
-Then install dependencies
-
-```bash
-yarn install
-```
-
-### Build
-
-To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
-
-```bash
-PKG=@0x/asset-buyer yarn build
-```
-
-Or continuously rebuild on change:
-
-```bash
-PKG=@0x/asset-buyer yarn watch
-```
-
-### Clean
-
-```bash
-yarn clean
-```
-
-### Lint
-
-```bash
-yarn lint
-```
-
-### Run Tests
-
-```bash
-yarn test
-```
diff --git a/packages/asset-buyer/package.json b/packages/asset-buyer/package.json
deleted file mode 100644
index 0f79ac06a..000000000
--- a/packages/asset-buyer/package.json
+++ /dev/null
@@ -1,74 +0,0 @@
-{
- "name": "@0x/asset-buyer",
- "version": "4.0.2",
- "engines": {
- "node": ">=6.12"
- },
- "description": "Convenience package for discovering and buying assets with Ether.",
- "main": "lib/src/index.js",
- "types": "lib/src/index.d.ts",
- "scripts": {
- "build": "yarn tsc -b",
- "build:ci": "yarn build",
- "lint": "tslint --format stylish --project .",
- "test": "yarn run_mocha",
- "rebuild_and_test": "run-s clean build test",
- "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
- "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
- "test:circleci": "yarn test:coverage",
- "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
- "clean": "shx rm -rf lib test_temp",
- "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
- },
- "config": {
- "postpublish": {
- "assets": []
- }
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/0xProject/0x-monorepo.git"
- },
- "author": "",
- "license": "Apache-2.0",
- "bugs": {
- "url": "https://github.com/0xProject/0x-monorepo/issues"
- },
- "homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md",
- "dependencies": {
- "@0x/assert": "^1.0.23",
- "@0x/connect": "^3.0.13",
- "@0x/contract-wrappers": "^5.0.1",
- "@0x/json-schemas": "^2.1.7",
- "@0x/order-utils": "^3.1.2",
- "@0x/subproviders": "^2.1.11",
- "@0x/types": "^1.5.2",
- "@0x/typescript-typings": "^3.0.8",
- "@0x/utils": "^3.0.1",
- "@0x/web3-wrapper": "^3.2.4",
- "ethereum-types": "^1.1.6",
- "lodash": "^4.17.5"
- },
- "devDependencies": {
- "@0x/tslint-config": "^2.0.2",
- "@types/lodash": "^4.14.116",
- "@types/mocha": "^2.2.42",
- "@types/node": "*",
- "chai": "^4.0.1",
- "chai-as-promised": "^7.1.0",
- "chai-bignumber": "^3.0.0",
- "dirty-chai": "^2.0.1",
- "make-promises-safe": "^1.1.0",
- "mocha": "^4.1.0",
- "npm-run-all": "^4.1.2",
- "nyc": "^11.0.1",
- "shx": "^0.2.2",
- "tslint": "5.11.0",
- "typedoc": "0.13.0",
- "typemoq": "^2.1.0",
- "typescript": "3.0.1"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts
deleted file mode 100644
index ad4b3bb60..000000000
--- a/packages/asset-buyer/src/asset_buyer.ts
+++ /dev/null
@@ -1,365 +0,0 @@
-import { ContractWrappers, ContractWrappersError, ForwarderWrapperError } from '@0x/contract-wrappers';
-import { schemas } from '@0x/json-schemas';
-import { SignedOrder } from '@0x/order-utils';
-import { ObjectMap } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import { Provider } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { constants } from './constants';
-import { BasicOrderProvider } from './order_providers/basic_order_provider';
-import { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
-import {
- AssetBuyerError,
- AssetBuyerOpts,
- BuyQuote,
- BuyQuoteExecutionOpts,
- BuyQuoteRequestOpts,
- LiquidityForAssetData,
- LiquidityRequestOpts,
- OrderProvider,
- OrdersAndFillableAmounts,
-} from './types';
-
-import { assert } from './utils/assert';
-import { assetDataUtils } from './utils/asset_data_utils';
-import { buyQuoteCalculator } from './utils/buy_quote_calculator';
-import { calculateLiquidity } from './utils/calculate_liquidity';
-import { orderProviderResponseProcessor } from './utils/order_provider_response_processor';
-
-interface OrdersEntry {
- ordersAndFillableAmounts: OrdersAndFillableAmounts;
- lastRefreshTime: number;
-}
-
-export class AssetBuyer {
- public readonly provider: Provider;
- public readonly orderProvider: OrderProvider;
- public readonly networkId: number;
- public readonly orderRefreshIntervalMs: number;
- public readonly expiryBufferSeconds: number;
- private readonly _contractWrappers: ContractWrappers;
- // cache of orders along with the time last updated keyed by assetData
- private readonly _ordersEntryMap: ObjectMap<OrdersEntry> = {};
- /**
- * Instantiates a new AssetBuyer instance given existing liquidity in the form of orders and feeOrders.
- * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
- * @param orders A non-empty array of objects that conform to SignedOrder. All orders must have the same makerAssetData and takerAssetData (WETH).
- * @param feeOrders A array of objects that conform to SignedOrder. All orders must have the same makerAssetData (ZRX) and takerAssetData (WETH). Defaults to an empty array.
- * @param options Initialization options for the AssetBuyer. See type definition for details.
- *
- * @return An instance of AssetBuyer
- */
- public static getAssetBuyerForProvidedOrders(
- provider: Provider,
- orders: SignedOrder[],
- options: Partial<AssetBuyerOpts> = {},
- ): AssetBuyer {
- assert.isWeb3Provider('provider', provider);
- assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
- assert.assert(orders.length !== 0, `Expected orders to contain at least one order`);
- const orderProvider = new BasicOrderProvider(orders);
- const assetBuyer = new AssetBuyer(provider, orderProvider, options);
- return assetBuyer;
- }
- /**
- * Instantiates a new AssetBuyer instance given a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) endpoint
- * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
- * @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
- * @param options Initialization options for the AssetBuyer. See type definition for details.
- *
- * @return An instance of AssetBuyer
- */
- public static getAssetBuyerForStandardRelayerAPIUrl(
- provider: Provider,
- sraApiUrl: string,
- options: Partial<AssetBuyerOpts> = {},
- ): AssetBuyer {
- assert.isWeb3Provider('provider', provider);
- assert.isWebUri('sraApiUrl', sraApiUrl);
- const networkId = options.networkId || constants.DEFAULT_ASSET_BUYER_OPTS.networkId;
- const orderProvider = new StandardRelayerAPIOrderProvider(sraApiUrl, networkId);
- const assetBuyer = new AssetBuyer(provider, orderProvider, options);
- return assetBuyer;
- }
- /**
- * Instantiates a new AssetBuyer instance
- * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
- * @param orderProvider An object that conforms to OrderProvider, see type for definition.
- * @param options Initialization options for the AssetBuyer. See type definition for details.
- *
- * @return An instance of AssetBuyer
- */
- constructor(provider: Provider, orderProvider: OrderProvider, options: Partial<AssetBuyerOpts> = {}) {
- const { networkId, orderRefreshIntervalMs, expiryBufferSeconds } = _.merge(
- {},
- constants.DEFAULT_ASSET_BUYER_OPTS,
- options,
- );
- assert.isWeb3Provider('provider', provider);
- assert.isValidOrderProvider('orderProvider', orderProvider);
- assert.isNumber('networkId', networkId);
- assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
- assert.isNumber('expiryBufferSeconds', expiryBufferSeconds);
- this.provider = provider;
- this.orderProvider = orderProvider;
- this.networkId = networkId;
- this.orderRefreshIntervalMs = orderRefreshIntervalMs;
- this.expiryBufferSeconds = expiryBufferSeconds;
- this._contractWrappers = new ContractWrappers(this.provider, {
- networkId,
- });
- }
- /**
- * Get a `BuyQuote` containing all information relevant to fulfilling a buy given a desired assetData.
- * You can then pass the `BuyQuote` to `executeBuyQuoteAsync` to execute the buy.
- * @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
- * @param assetBuyAmount The amount of asset to buy.
- * @param options Options for the request. See type definition for more information.
- *
- * @return An object that conforms to BuyQuote that satisfies the request. See type definition for more information.
- */
- public async getBuyQuoteAsync(
- assetData: string,
- assetBuyAmount: BigNumber,
- options: Partial<BuyQuoteRequestOpts> = {},
- ): Promise<BuyQuote> {
- const { feePercentage, shouldForceOrderRefresh, slippagePercentage } = _.merge(
- {},
- constants.DEFAULT_BUY_QUOTE_REQUEST_OPTS,
- options,
- );
- assert.isString('assetData', assetData);
- assert.isBigNumber('assetBuyAmount', assetBuyAmount);
- assert.isValidPercentage('feePercentage', feePercentage);
- assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh);
- assert.isNumber('slippagePercentage', slippagePercentage);
- const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
- const isMakerAssetZrxToken = assetData === zrxTokenAssetData;
- // get the relevant orders for the makerAsset and fees
- // if the requested assetData is ZRX, don't get the fee info
- const [ordersAndFillableAmounts, feeOrdersAndFillableAmounts] = await Promise.all([
- this.getOrdersAndFillableAmountsAsync(assetData, shouldForceOrderRefresh),
- isMakerAssetZrxToken
- ? Promise.resolve(constants.EMPTY_ORDERS_AND_FILLABLE_AMOUNTS)
- : this.getOrdersAndFillableAmountsAsync(zrxTokenAssetData, shouldForceOrderRefresh),
- shouldForceOrderRefresh,
- ]);
- if (ordersAndFillableAmounts.orders.length === 0) {
- throw new Error(`${AssetBuyerError.AssetUnavailable}: For assetData ${assetData}`);
- }
- const buyQuote = buyQuoteCalculator.calculate(
- ordersAndFillableAmounts,
- feeOrdersAndFillableAmounts,
- assetBuyAmount,
- feePercentage,
- slippagePercentage,
- isMakerAssetZrxToken,
- );
- return buyQuote;
- }
- /**
- * Get a `BuyQuote` containing all information relevant to fulfilling a buy given a desired ERC20 token address.
- * You can then pass the `BuyQuote` to `executeBuyQuoteAsync` to execute the buy.
- * @param tokenAddress The ERC20 token address.
- * @param assetBuyAmount The amount of asset to buy.
- * @param options Options for the request. See type definition for more information.
- *
- * @return An object that conforms to BuyQuote that satisfies the request. See type definition for more information.
- */
- public async getBuyQuoteForERC20TokenAddressAsync(
- tokenAddress: string,
- assetBuyAmount: BigNumber,
- options: Partial<BuyQuoteRequestOpts> = {},
- ): Promise<BuyQuote> {
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.isBigNumber('assetBuyAmount', assetBuyAmount);
- const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
- const buyQuote = this.getBuyQuoteAsync(assetData, assetBuyAmount, options);
- return buyQuote;
- }
- /**
- * Returns information about available liquidity for an asset
- * Does not factor in slippage or fees
- * @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
- * @param options Options for the request. See type definition for more information.
- *
- * @return An object that conforms to LiquidityForAssetData that satisfies the request. See type definition for more information.
- */
- public async getLiquidityForAssetDataAsync(
- assetData: string,
- options: Partial<LiquidityRequestOpts> = {},
- ): Promise<LiquidityForAssetData> {
- const shouldForceOrderRefresh =
- options.shouldForceOrderRefresh !== undefined ? options.shouldForceOrderRefresh : false;
- assetDataUtils.decodeAssetDataOrThrow(assetData);
- assert.isBoolean('options.shouldForceOrderRefresh', shouldForceOrderRefresh);
-
- const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData);
- const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow();
- if (!assetPairs.includes(etherTokenAssetData)) {
- return {
- tokensAvailableInBaseUnits: new BigNumber(0),
- ethValueAvailableInWei: new BigNumber(0),
- };
- }
-
- const ordersAndFillableAmounts = await this.getOrdersAndFillableAmountsAsync(
- assetData,
- shouldForceOrderRefresh,
- );
-
- return calculateLiquidity(ordersAndFillableAmounts);
- }
-
- /**
- * Given a BuyQuote and desired rate, attempt to execute the buy.
- * @param buyQuote An object that conforms to BuyQuote. See type definition for more information.
- * @param options Options for the execution of the BuyQuote. See type definition for more information.
- *
- * @return A promise of the txHash.
- */
- public async executeBuyQuoteAsync(
- buyQuote: BuyQuote,
- options: Partial<BuyQuoteExecutionOpts> = {},
- ): Promise<string> {
- const { ethAmount, takerAddress, feeRecipient, gasLimit, gasPrice } = _.merge(
- {},
- constants.DEFAULT_BUY_QUOTE_EXECUTION_OPTS,
- options,
- );
- assert.isValidBuyQuote('buyQuote', buyQuote);
- if (!_.isUndefined(ethAmount)) {
- assert.isBigNumber('ethAmount', ethAmount);
- }
- if (!_.isUndefined(takerAddress)) {
- assert.isETHAddressHex('takerAddress', takerAddress);
- }
- assert.isETHAddressHex('feeRecipient', feeRecipient);
- if (!_.isUndefined(gasLimit)) {
- assert.isNumber('gasLimit', gasLimit);
- }
- if (!_.isUndefined(gasPrice)) {
- assert.isBigNumber('gasPrice', gasPrice);
- }
- const { orders, feeOrders, feePercentage, assetBuyAmount, worstCaseQuoteInfo } = buyQuote;
- // if no takerAddress is provided, try to get one from the provider
- let finalTakerAddress;
- if (!_.isUndefined(takerAddress)) {
- finalTakerAddress = takerAddress;
- } else {
- const web3Wrapper = new Web3Wrapper(this.provider);
- const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
- const firstAvailableAddress = _.head(availableAddresses);
- if (!_.isUndefined(firstAvailableAddress)) {
- finalTakerAddress = firstAvailableAddress;
- } else {
- throw new Error(AssetBuyerError.NoAddressAvailable);
- }
- }
- try {
- // if no ethAmount is provided, default to the worst ethAmount from buyQuote
- const txHash = await this._contractWrappers.forwarder.marketBuyOrdersWithEthAsync(
- orders,
- assetBuyAmount,
- finalTakerAddress,
- ethAmount || worstCaseQuoteInfo.totalEthAmount,
- feeOrders,
- feePercentage,
- feeRecipient,
- {
- gasLimit,
- gasPrice,
- shouldValidate: true,
- },
- );
- return txHash;
- } catch (err) {
- if (_.includes(err.message, ContractWrappersError.SignatureRequestDenied)) {
- throw new Error(AssetBuyerError.SignatureRequestDenied);
- } else if (_.includes(err.message, ForwarderWrapperError.CompleteFillFailed)) {
- throw new Error(AssetBuyerError.TransactionValueTooLow);
- } else {
- throw err;
- }
- }
- }
- /**
- * Get the asset data of all assets that are purchaseable with ether token (wETH) in the order provider passed in at init.
- *
- * @return An array of asset data strings that can be purchased using wETH.
- */
- public async getAvailableAssetDatasAsync(): Promise<string[]> {
- const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow();
- return this.orderProvider.getAvailableMakerAssetDatasAsync(etherTokenAssetData);
- }
- /**
- * Grab orders from the map, if there is a miss or it is time to refresh, fetch and process the orders
- * @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
- * @param shouldForceOrderRefresh If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs.
- */
- public async getOrdersAndFillableAmountsAsync(
- assetData: string,
- shouldForceOrderRefresh: boolean,
- ): Promise<OrdersAndFillableAmounts> {
- // try to get ordersEntry from the map
- const ordersEntryIfExists = this._ordersEntryMap[assetData];
- // we should refresh if:
- // we do not have any orders OR
- // we are forced to OR
- // we have some last refresh time AND that time was sufficiently long ago
- const shouldRefresh =
- _.isUndefined(ordersEntryIfExists) ||
- shouldForceOrderRefresh ||
- // tslint:disable:restrict-plus-operands
- ordersEntryIfExists.lastRefreshTime + this.orderRefreshIntervalMs < Date.now();
- if (!shouldRefresh) {
- const result = ordersEntryIfExists.ordersAndFillableAmounts;
- return result;
- }
- const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow();
- const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
- // construct orderProvider request
- const orderProviderRequest = {
- makerAssetData: assetData,
- takerAssetData: etherTokenAssetData,
- networkId: this.networkId,
- };
- const request = orderProviderRequest;
- // get provider response
- const response = await this.orderProvider.getOrdersAsync(request);
- // 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(response, request);
- // process the responses into one object
- const isMakerAssetZrxToken = assetData === zrxTokenAssetData;
- const ordersAndFillableAmounts = await orderProviderResponseProcessor.processAsync(
- response,
- isMakerAssetZrxToken,
- this.expiryBufferSeconds,
- this._contractWrappers.orderValidator,
- );
- const lastRefreshTime = Date.now();
- const updatedOrdersEntry = {
- ordersAndFillableAmounts,
- lastRefreshTime,
- };
- this._ordersEntryMap[assetData] = updatedOrdersEntry;
- return ordersAndFillableAmounts;
- }
- /**
- * Get the assetData that represents the WETH token.
- * Will throw if WETH does not exist for the current network.
- */
- private _getEtherTokenAssetDataOrThrow(): string {
- return assetDataUtils.getEtherTokenAssetData(this._contractWrappers);
- }
- /**
- * Get the assetData that represents the ZRX token.
- * Will throw if ZRX does not exist for the current network.
- */
- private _getZrxTokenAssetDataOrThrow(): string {
- return this._contractWrappers.exchange.getZRXAssetData();
- }
-}
diff --git a/packages/asset-buyer/src/constants.ts b/packages/asset-buyer/src/constants.ts
deleted file mode 100644
index c0e1bf27d..000000000
--- a/packages/asset-buyer/src/constants.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-
-import { AssetBuyerOpts, BuyQuoteExecutionOpts, BuyQuoteRequestOpts, OrdersAndFillableAmounts } from './types';
-
-const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
-const MAINNET_NETWORK_ID = 1;
-
-const DEFAULT_ASSET_BUYER_OPTS: AssetBuyerOpts = {
- networkId: MAINNET_NETWORK_ID,
- orderRefreshIntervalMs: 10000, // 10 seconds
- expiryBufferSeconds: 120, // 2 minutes
-};
-
-const DEFAULT_BUY_QUOTE_REQUEST_OPTS: BuyQuoteRequestOpts = {
- feePercentage: 0,
- shouldForceOrderRefresh: false,
- slippagePercentage: 0.2, // 20% slippage protection
-};
-
-// Other default values are dynamically determined
-const DEFAULT_BUY_QUOTE_EXECUTION_OPTS: BuyQuoteExecutionOpts = {
- feeRecipient: NULL_ADDRESS,
-};
-
-const EMPTY_ORDERS_AND_FILLABLE_AMOUNTS: OrdersAndFillableAmounts = {
- orders: [] as SignedOrder[],
- remainingFillableMakerAssetAmounts: [] as BigNumber[],
-};
-
-export const constants = {
- ZERO_AMOUNT: new BigNumber(0),
- NULL_ADDRESS,
- MAINNET_NETWORK_ID,
- ETHER_TOKEN_DECIMALS: 18,
- DEFAULT_ASSET_BUYER_OPTS,
- DEFAULT_BUY_QUOTE_EXECUTION_OPTS,
- DEFAULT_BUY_QUOTE_REQUEST_OPTS,
- EMPTY_ORDERS_AND_FILLABLE_AMOUNTS,
-};
diff --git a/packages/asset-buyer/src/errors.ts b/packages/asset-buyer/src/errors.ts
deleted file mode 100644
index ec5fe548c..000000000
--- a/packages/asset-buyer/src/errors.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { BigNumber } from '@0x/utils';
-
-import { AssetBuyerError } from './types';
-
-/**
- * Error class representing insufficient asset liquidity
- */
-export class InsufficientAssetLiquidityError extends Error {
- /**
- * The amount availabe to fill (in base units) factoring in slippage.
- */
- public amountAvailableToFill: BigNumber;
- /**
- * @param amountAvailableToFill The amount availabe to fill (in base units) factoring in slippage
- */
- constructor(amountAvailableToFill: BigNumber) {
- super(AssetBuyerError.InsufficientAssetLiquidity);
- this.amountAvailableToFill = amountAvailableToFill;
- // Setting prototype so instanceof works. See https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
- Object.setPrototypeOf(this, InsufficientAssetLiquidityError.prototype);
- }
-}
diff --git a/packages/asset-buyer/src/globals.d.ts b/packages/asset-buyer/src/globals.d.ts
deleted file mode 100644
index 94e63a32d..000000000
--- a/packages/asset-buyer/src/globals.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module '*.json' {
- const json: any;
- /* tslint:disable */
- export default json;
- /* tslint:enable */
-}
diff --git a/packages/asset-buyer/src/index.ts b/packages/asset-buyer/src/index.ts
deleted file mode 100644
index f69cfad69..000000000
--- a/packages/asset-buyer/src/index.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-export {
- JSONRPCRequestPayload,
- JSONRPCResponsePayload,
- JSONRPCResponseError,
- JSONRPCErrorCallback,
- Provider,
-} from 'ethereum-types';
-export { SignedOrder } from '@0x/types';
-export { BigNumber } from '@0x/utils';
-
-export { AssetBuyer } from './asset_buyer';
-export { InsufficientAssetLiquidityError } from './errors';
-export { BasicOrderProvider } from './order_providers/basic_order_provider';
-export { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
-export {
- AssetBuyerError,
- AssetBuyerOpts,
- BuyQuote,
- BuyQuoteExecutionOpts,
- BuyQuoteInfo,
- BuyQuoteRequestOpts,
- LiquidityForAssetData,
- LiquidityRequestOpts,
- OrdersAndFillableAmounts,
- OrderProvider,
- OrderProviderRequest,
- OrderProviderResponse,
- SignedOrderWithRemainingFillableMakerAssetAmount,
-} from './types';
diff --git a/packages/asset-buyer/src/order_providers/basic_order_provider.ts b/packages/asset-buyer/src/order_providers/basic_order_provider.ts
deleted file mode 100644
index 76685f27a..000000000
--- a/packages/asset-buyer/src/order_providers/basic_order_provider.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { schemas } from '@0x/json-schemas';
-import { SignedOrder } from '@0x/types';
-import * as _ from 'lodash';
-
-import { OrderProvider, OrderProviderRequest, OrderProviderResponse } from '../types';
-import { assert } from '../utils/assert';
-
-export class BasicOrderProvider implements OrderProvider {
- public readonly orders: SignedOrder[];
- /**
- * Instantiates a new BasicOrderProvider instance
- * @param orders An array of objects that conform to SignedOrder to fetch from.
- * @return An instance of BasicOrderProvider
- */
- constructor(orders: SignedOrder[]) {
- assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
- this.orders = orders;
- }
- /**
- * Given an object that conforms to OrderFetcherRequest, return the corresponding OrderProviderResponse that satisfies the request.
- * @param orderProviderRequest An instance of OrderFetcherRequest. See type for more information.
- * @return An instance of OrderProviderResponse. See type for more information.
- */
- public async getOrdersAsync(orderProviderRequest: OrderProviderRequest): Promise<OrderProviderResponse> {
- assert.isValidOrderProviderRequest('orderProviderRequest', orderProviderRequest);
- const { makerAssetData, takerAssetData } = orderProviderRequest;
- const orders = _.filter(this.orders, order => {
- return order.makerAssetData === makerAssetData && order.takerAssetData === takerAssetData;
- });
- return { orders };
- }
- /**
- * Given a taker asset data string, return all availabled paired maker asset data strings.
- * @param takerAssetData A string representing the taker asset data.
- * @return An array of asset data strings that can be purchased using takerAssetData.
- */
- public async getAvailableMakerAssetDatasAsync(takerAssetData: string): Promise<string[]> {
- const ordersWithTakerAssetData = _.filter(this.orders, { takerAssetData });
- return _.map(ordersWithTakerAssetData, order => order.makerAssetData);
- }
-}
diff --git a/packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts b/packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts
deleted file mode 100644
index 813c9923b..000000000
--- a/packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import { HttpClient } from '@0x/connect';
-import { APIOrder, AssetPairsResponse, OrderbookResponse } from '@0x/types';
-import * as _ from 'lodash';
-
-import {
- AssetBuyerError,
- OrderProvider,
- OrderProviderRequest,
- OrderProviderResponse,
- SignedOrderWithRemainingFillableMakerAssetAmount,
-} from '../types';
-import { assert } from '../utils/assert';
-import { orderUtils } from '../utils/order_utils';
-
-export class StandardRelayerAPIOrderProvider implements OrderProvider {
- public readonly apiUrl: string;
- public readonly networkId: number;
- private readonly _sraClient: HttpClient;
- /**
- * Given an array of APIOrder objects from a standard relayer api, return an array
- * of SignedOrderWithRemainingFillableMakerAssetAmounts
- */
- private static _getSignedOrderWithRemainingFillableMakerAssetAmountFromApi(
- apiOrders: APIOrder[],
- ): SignedOrderWithRemainingFillableMakerAssetAmount[] {
- const result = _.map(apiOrders, apiOrder => {
- const { order, metaData } = apiOrder;
- // calculate remainingFillableMakerAssetAmount from api metadata, else assume order is completely fillable
- const remainingFillableTakerAssetAmount = _.get(
- metaData,
- 'remainingTakerAssetAmount',
- order.takerAssetAmount,
- );
- const remainingFillableMakerAssetAmount = orderUtils.getRemainingMakerAmount(
- order,
- remainingFillableTakerAssetAmount,
- );
- const newOrder = {
- ...order,
- remainingFillableMakerAssetAmount,
- };
- return newOrder;
- });
- return result;
- }
- /**
- * Instantiates a new StandardRelayerAPIOrderProvider instance
- * @param apiUrl The standard relayer API base HTTP url you would like to source orders from.
- * @param networkId The ethereum network id.
- * @return An instance of StandardRelayerAPIOrderProvider
- */
- constructor(apiUrl: string, networkId: number) {
- assert.isWebUri('apiUrl', apiUrl);
- assert.isNumber('networkId', networkId);
- this.apiUrl = apiUrl;
- this.networkId = networkId;
- this._sraClient = new HttpClient(apiUrl);
- }
- /**
- * Given an object that conforms to OrderProviderRequest, return the corresponding OrderProviderResponse that satisfies the request.
- * @param orderProviderRequest An instance of OrderProviderRequest. See type for more information.
- * @return An instance of OrderProviderResponse. See type for more information.
- */
- public async getOrdersAsync(orderProviderRequest: OrderProviderRequest): Promise<OrderProviderResponse> {
- assert.isValidOrderProviderRequest('orderProviderRequest', orderProviderRequest);
- const { makerAssetData, takerAssetData } = orderProviderRequest;
- const orderbookRequest = { baseAssetData: makerAssetData, quoteAssetData: takerAssetData };
- const requestOpts = { networkId: this.networkId };
- let orderbook: OrderbookResponse;
- try {
- orderbook = await this._sraClient.getOrderbookAsync(orderbookRequest, requestOpts);
- } catch (err) {
- throw new Error(AssetBuyerError.StandardRelayerApiError);
- }
- const apiOrders = orderbook.asks.records;
- const orders = StandardRelayerAPIOrderProvider._getSignedOrderWithRemainingFillableMakerAssetAmountFromApi(
- apiOrders,
- );
- return {
- orders,
- };
- }
- /**
- * Given a taker asset data string, return all availabled paired maker asset data strings.
- * @param takerAssetData A string representing the taker asset data.
- * @return An array of asset data strings that can be purchased using takerAssetData.
- */
- public async getAvailableMakerAssetDatasAsync(takerAssetData: string): Promise<string[]> {
- // Return a maximum of 1000 asset datas
- const maxPerPage = 1000;
- const requestOpts = { networkId: this.networkId, perPage: maxPerPage };
- const assetPairsRequest = { assetDataA: takerAssetData };
- const fullRequest = {
- ...requestOpts,
- ...assetPairsRequest,
- };
- let response: AssetPairsResponse;
- try {
- response = await this._sraClient.getAssetPairsAsync(fullRequest);
- } catch (err) {
- throw new Error(AssetBuyerError.StandardRelayerApiError);
- }
- return _.map(response.records, item => {
- if (item.assetDataA.assetData === takerAssetData) {
- return item.assetDataB.assetData;
- } else {
- return item.assetDataA.assetData;
- }
- });
- }
-}
diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts
deleted file mode 100644
index 46a2338ce..000000000
--- a/packages/asset-buyer/src/types.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-
-/**
- * makerAssetData: The assetData representing the desired makerAsset.
- * takerAssetData: The assetData representing the desired takerAsset.
- * networkId: The networkId that the desired orders should be for.
- */
-export interface OrderProviderRequest {
- makerAssetData: string;
- takerAssetData: string;
-}
-
-/**
- * orders: An array of orders with optional remaining fillable makerAsset amounts. See type for more info.
- */
-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;
-}
-/**
- * gerOrdersAsync: Given an OrderProviderRequest, get an OrderProviderResponse.
- * getAvailableMakerAssetDatasAsync: Given a taker asset data string, return all availabled paired maker asset data strings.
- */
-export interface OrderProvider {
- getOrdersAsync: (orderProviderRequest: OrderProviderRequest) => Promise<OrderProviderResponse>;
- getAvailableMakerAssetDatasAsync: (takerAssetData: string) => Promise<string[]>;
-}
-
-/**
- * assetData: String that represents a specific asset (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
- * assetBuyAmount: The amount of asset to buy.
- * 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.
- * feePercentage: Optional affiliate fee percentage used to calculate the eth amounts above.
- * bestCaseQuoteInfo: Info about the best case price for the asset.
- * worstCaseQuoteInfo: Info about the worst case price for the asset.
- */
-export interface BuyQuote {
- assetData: string;
- assetBuyAmount: BigNumber;
- orders: SignedOrder[];
- feeOrders: SignedOrder[];
- feePercentage?: number;
- bestCaseQuoteInfo: BuyQuoteInfo;
- worstCaseQuoteInfo: BuyQuoteInfo;
-}
-
-/**
- * assetEthAmount: The amount of eth required to pay for the requested asset.
- * feeEthAmount: The amount of eth required to pay the affiliate fee.
- * totalEthAmount: The total amount of eth required to complete the buy (filling orders, feeOrders, and paying affiliate fee).
- */
-export interface BuyQuoteInfo {
- assetEthAmount: BigNumber;
- feeEthAmount: BigNumber;
- totalEthAmount: BigNumber;
-}
-
-/**
- * feePercentage: The affiliate fee percentage. Defaults to 0.
- * shouldForceOrderRefresh: If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs. Defaults to false.
- * slippagePercentage: The percentage buffer to add to account for slippage. Affects max ETH price estimates. Defaults to 0.2 (20%).
- */
-export interface BuyQuoteRequestOpts {
- feePercentage: number;
- shouldForceOrderRefresh: boolean;
- slippagePercentage: number;
-}
-
-/*
- * Options for checking liquidity
- *
- * shouldForceOrderRefresh: If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs. Defaults to false.
- */
-export type LiquidityRequestOpts = Pick<BuyQuoteRequestOpts, 'shouldForceOrderRefresh'>;
-
-/**
- * ethAmount: The desired amount of eth to spend. Defaults to buyQuote.worstCaseQuoteInfo.totalEthAmount.
- * 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
- * feeRecipient: The address where affiliate fees are sent. Defaults to null address (0x000...000).
- */
-export interface BuyQuoteExecutionOpts {
- ethAmount?: BigNumber;
- takerAddress?: string;
- gasLimit?: number;
- gasPrice?: BigNumber;
- feeRecipient: string;
-}
-
-/**
- * networkId: The ethereum network id. Defaults to 1 (mainnet).
- * orderRefreshIntervalMs: The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
- * expiryBufferSeconds: The number of seconds to add when calculating whether an order is expired or not. Defaults to 300s (5m).
- */
-export interface AssetBuyerOpts {
- networkId: number;
- orderRefreshIntervalMs: number;
- expiryBufferSeconds: number;
-}
-
-/**
- * Possible error messages thrown by an AssetBuyer instance or associated static methods.
- */
-export enum AssetBuyerError {
- 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',
- NoAddressAvailable = 'NO_ADDRESS_AVAILABLE',
- InvalidOrderProviderResponse = 'INVALID_ORDER_PROVIDER_RESPONSE',
- AssetUnavailable = 'ASSET_UNAVAILABLE',
- SignatureRequestDenied = 'SIGNATURE_REQUEST_DENIED',
- TransactionValueTooLow = 'TRANSACTION_VALUE_TOO_LOW',
-}
-
-/**
- * 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.
- */
-export interface OrdersAndFillableAmounts {
- orders: SignedOrder[];
- remainingFillableMakerAssetAmounts: BigNumber[];
-}
-
-/**
- * Represents available liquidity for a given assetData
- */
-export interface LiquidityForAssetData {
- tokensAvailableInBaseUnits: BigNumber;
- ethValueAvailableInWei: BigNumber;
-}
diff --git a/packages/asset-buyer/src/utils/assert.ts b/packages/asset-buyer/src/utils/assert.ts
deleted file mode 100644
index fcf9b0d0e..000000000
--- a/packages/asset-buyer/src/utils/assert.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { assert as sharedAssert } from '@0x/assert';
-import { schemas } from '@0x/json-schemas';
-import * as _ from 'lodash';
-
-import { BuyQuote, BuyQuoteInfo, OrderProvider, OrderProviderRequest } from '../types';
-
-export const assert = {
- ...sharedAssert,
- isValidBuyQuote(variableName: string, buyQuote: BuyQuote): void {
- sharedAssert.isHexString(`${variableName}.assetData`, buyQuote.assetData);
- sharedAssert.doesConformToSchema(`${variableName}.orders`, buyQuote.orders, schemas.signedOrdersSchema);
- sharedAssert.doesConformToSchema(`${variableName}.feeOrders`, buyQuote.feeOrders, schemas.signedOrdersSchema);
- assert.isValidBuyQuoteInfo(`${variableName}.bestCaseQuoteInfo`, buyQuote.bestCaseQuoteInfo);
- assert.isValidBuyQuoteInfo(`${variableName}.worstCaseQuoteInfo`, buyQuote.worstCaseQuoteInfo);
- sharedAssert.isBigNumber(`${variableName}.assetBuyAmount`, buyQuote.assetBuyAmount);
- if (!_.isUndefined(buyQuote.feePercentage)) {
- sharedAssert.isNumber(`${variableName}.feePercentage`, buyQuote.feePercentage);
- }
- },
- isValidBuyQuoteInfo(variableName: string, buyQuoteInfo: BuyQuoteInfo): void {
- sharedAssert.isBigNumber(`${variableName}.assetEthAmount`, buyQuoteInfo.assetEthAmount);
- sharedAssert.isBigNumber(`${variableName}.feeEthAmount`, buyQuoteInfo.feeEthAmount);
- sharedAssert.isBigNumber(`${variableName}.totalEthAmount`, buyQuoteInfo.totalEthAmount);
- },
- isValidOrderProvider(variableName: string, orderFetcher: OrderProvider): void {
- sharedAssert.isFunction(`${variableName}.getOrdersAsync`, orderFetcher.getOrdersAsync);
- },
- isValidOrderProviderRequest(variableName: string, orderFetcherRequest: OrderProviderRequest): void {
- sharedAssert.isHexString(`${variableName}.makerAssetData`, orderFetcherRequest.makerAssetData);
- sharedAssert.isHexString(`${variableName}.takerAssetData`, orderFetcherRequest.takerAssetData);
- },
- isValidPercentage(variableName: string, percentage: number): void {
- assert.isNumber(variableName, percentage);
- assert.assert(
- percentage >= 0 && percentage <= 1,
- `Expected ${variableName} to be between 0 and 1, but is ${percentage}`,
- );
- },
-};
diff --git a/packages/asset-buyer/src/utils/asset_data_utils.ts b/packages/asset-buyer/src/utils/asset_data_utils.ts
deleted file mode 100644
index 70f646902..000000000
--- a/packages/asset-buyer/src/utils/asset_data_utils.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { ContractWrappers } from '@0x/contract-wrappers';
-import { assetDataUtils as sharedAssetDataUtils } from '@0x/order-utils';
-import * as _ from 'lodash';
-
-export const assetDataUtils = {
- ...sharedAssetDataUtils,
- getEtherTokenAssetData(contractWrappers: ContractWrappers): string {
- const etherTokenAddress = contractWrappers.forwarder.etherTokenAddress;
- const etherTokenAssetData = sharedAssetDataUtils.encodeERC20AssetData(etherTokenAddress);
- return etherTokenAssetData;
- },
-};
diff --git a/packages/asset-buyer/src/utils/buy_quote_calculator.ts b/packages/asset-buyer/src/utils/buy_quote_calculator.ts
deleted file mode 100644
index 125841094..000000000
--- a/packages/asset-buyer/src/utils/buy_quote_calculator.ts
+++ /dev/null
@@ -1,221 +0,0 @@
-import { marketUtils, SignedOrder } from '@0x/order-utils';
-import { BigNumber } from '@0x/utils';
-import * as _ from 'lodash';
-
-import { constants } from '../constants';
-import { InsufficientAssetLiquidityError } from '../errors';
-import { AssetBuyerError, BuyQuote, BuyQuoteInfo, OrdersAndFillableAmounts } from '../types';
-
-import { orderUtils } from './order_utils';
-
-// Calculates a buy quote for orders that have WETH as the takerAsset
-export const buyQuoteCalculator = {
- calculate(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- assetBuyAmount: BigNumber,
- feePercentage: number,
- slippagePercentage: number,
- isMakerAssetZrxToken: boolean,
- ): BuyQuote {
- const orders = ordersAndFillableAmounts.orders;
- const remainingFillableMakerAssetAmounts = ordersAndFillableAmounts.remainingFillableMakerAssetAmounts;
- const feeOrders = feeOrdersAndFillableAmounts.orders;
- const remainingFillableFeeAmounts = feeOrdersAndFillableAmounts.remainingFillableMakerAssetAmounts;
- const slippageBufferAmount = assetBuyAmount.multipliedBy(slippagePercentage).integerValue();
- // find the orders that cover the desired assetBuyAmount (with slippage)
- const {
- resultOrders,
- remainingFillAmount,
- ordersRemainingFillableMakerAssetAmounts,
- } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(orders, assetBuyAmount, {
- remainingFillableMakerAssetAmounts,
- slippageBufferAmount,
- });
- // if we do not have enough orders to cover the desired assetBuyAmount, throw
- if (remainingFillAmount.gt(constants.ZERO_AMOUNT)) {
- // We needed the amount they requested to buy, plus the amount for slippage
- const totalAmountRequested = assetBuyAmount.plus(slippageBufferAmount);
- const amountAbleToFill = totalAmountRequested.minus(remainingFillAmount);
- // multiplierNeededWithSlippage represents what we need to multiply the assetBuyAmount by
- // in order to get the total amount needed considering slippage
- // i.e. if slippagePercent was 0.2 (20%), multiplierNeededWithSlippage would be 1.2
- const multiplierNeededWithSlippage = new BigNumber(1).plus(slippagePercentage);
- // Given amountAvailableToFillConsideringSlippage * multiplierNeededWithSlippage = amountAbleToFill
- // We divide amountUnableToFill by multiplierNeededWithSlippage to determine amountAvailableToFillConsideringSlippage
- const amountAvailableToFillConsideringSlippage = amountAbleToFill
- .div(multiplierNeededWithSlippage)
- .integerValue(BigNumber.ROUND_FLOOR);
-
- 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 (!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(AssetBuyerError.InsufficientZrxLiquidity);
- }
- resultFeeOrders = feeOrdersAndRemainingFeeAmount.resultFeeOrders;
- feeOrdersRemainingFillableMakerAssetAmounts =
- feeOrdersAndRemainingFeeAmount.feeOrdersRemainingFillableMakerAssetAmounts;
- }
-
- // assetData information for the result
- const assetData = orders[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,
- assetBuyAmount,
- feePercentage,
- isMakerAssetZrxToken,
- );
- // 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),
- assetBuyAmount,
- feePercentage,
- isMakerAssetZrxToken,
- );
- return {
- assetData,
- orders: resultOrders,
- feeOrders: resultFeeOrders,
- bestCaseQuoteInfo,
- worstCaseQuoteInfo,
- assetBuyAmount,
- feePercentage,
- };
- },
-};
-
-function calculateQuoteInfo(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- assetBuyAmount: BigNumber,
- feePercentage: number,
- isMakerAssetZrxToken: boolean,
-): BuyQuoteInfo {
- // find the total eth and zrx needed to buy assetAmount from the resultOrders from left to right
- let assetEthAmount = constants.ZERO_AMOUNT;
- let zrxEthAmount = constants.ZERO_AMOUNT;
- if (isMakerAssetZrxToken) {
- assetEthAmount = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount);
- } else {
- // find eth and zrx amounts needed to buy
- const ethAndZrxAmountToBuyAsset = findEthAndZrxAmountNeededToBuyAsset(ordersAndFillableAmounts, assetBuyAmount);
- assetEthAmount = ethAndZrxAmountToBuyAsset[0];
- const zrxAmountToBuyAsset = ethAndZrxAmountToBuyAsset[1];
- // find eth amount needed to buy zrx
- zrxEthAmount = findEthAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset);
- }
- // eth amount needed to buy the affiliate fee
- const affiliateFeeEthAmount = assetEthAmount.multipliedBy(feePercentage).integerValue(BigNumber.ROUND_CEIL);
- // eth amount needed for fees is the sum of affiliate fee and zrx fee
- const feeEthAmount = affiliateFeeEthAmount.plus(zrxEthAmount);
- // eth amount needed in total is the sum of the amount needed for the asset and the amount needed for fees
- const totalEthAmount = assetEthAmount.plus(feeEthAmount);
- return {
- assetEthAmount,
- feeEthAmount,
- totalEthAmount,
- };
-}
-
-// 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 findEthAmountNeededToBuyZrx(
- feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
- zrxBuyAmount: BigNumber,
-): BigNumber {
- const { orders, remainingFillableMakerAssetAmounts } = feeOrdersAndFillableAmounts;
- const result = _.reduce(
- orders,
- (acc, order, index) => {
- const { totalEthAmount, remainingZrxBuyAmount } = acc;
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- const makerFillAmount = BigNumber.min(remainingZrxBuyAmount, remainingFillableMakerAssetAmount);
- const [takerFillAmount, adjustedMakerFillAmount] = orderUtils.getTakerFillAmountForFeeOrder(
- order,
- makerFillAmount,
- );
- const extraFeeAmount = remainingFillableMakerAssetAmount.isGreaterThanOrEqualTo(adjustedMakerFillAmount)
- ? constants.ZERO_AMOUNT
- : adjustedMakerFillAmount.minus(makerFillAmount);
- return {
- totalEthAmount: totalEthAmount.plus(takerFillAmount),
- remainingZrxBuyAmount: BigNumber.max(
- constants.ZERO_AMOUNT,
- remainingZrxBuyAmount.minus(makerFillAmount).plus(extraFeeAmount),
- ),
- };
- },
- {
- totalEthAmount: constants.ZERO_AMOUNT,
- remainingZrxBuyAmount: zrxBuyAmount,
- },
- );
- return result.totalEthAmount;
-}
-
-function findEthAndZrxAmountNeededToBuyAsset(
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- assetBuyAmount: BigNumber,
-): [BigNumber, BigNumber] {
- const { orders, remainingFillableMakerAssetAmounts } = ordersAndFillableAmounts;
- const result = _.reduce(
- orders,
- (acc, order, index) => {
- const { totalEthAmount, totalZrxAmount, remainingAssetBuyAmount } = acc;
- const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
- const makerFillAmount = BigNumber.min(acc.remainingAssetBuyAmount, remainingFillableMakerAssetAmount);
- const takerFillAmount = orderUtils.getTakerFillAmount(order, makerFillAmount);
- const takerFeeAmount = orderUtils.getTakerFeeAmount(order, takerFillAmount);
- return {
- totalEthAmount: totalEthAmount.plus(takerFillAmount),
- totalZrxAmount: totalZrxAmount.plus(takerFeeAmount),
- remainingAssetBuyAmount: BigNumber.max(
- constants.ZERO_AMOUNT,
- remainingAssetBuyAmount.minus(makerFillAmount),
- ),
- };
- },
- {
- totalEthAmount: constants.ZERO_AMOUNT,
- totalZrxAmount: constants.ZERO_AMOUNT,
- remainingAssetBuyAmount: assetBuyAmount,
- },
- );
- return [result.totalEthAmount, result.totalZrxAmount];
-}
diff --git a/packages/asset-buyer/src/utils/calculate_liquidity.ts b/packages/asset-buyer/src/utils/calculate_liquidity.ts
deleted file mode 100644
index a8d165b4b..000000000
--- a/packages/asset-buyer/src/utils/calculate_liquidity.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { BigNumber } from '@0x/utils';
-
-import { LiquidityForAssetData, OrdersAndFillableAmounts } from '../types';
-
-import { orderUtils } from './order_utils';
-
-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}`);
- }
-
- const tokensAvailableForCurrentOrder = availableMakerAssetAmount;
- const ethValueAvailableForCurrentOrder = orderUtils.getTakerFillAmount(order, availableMakerAssetAmount);
- return {
- tokensAvailableInBaseUnits: acc.tokensAvailableInBaseUnits.plus(tokensAvailableForCurrentOrder),
- ethValueAvailableInWei: acc.ethValueAvailableInWei.plus(ethValueAvailableForCurrentOrder),
- };
- },
- {
- tokensAvailableInBaseUnits: new BigNumber(0),
- ethValueAvailableInWei: new BigNumber(0),
- },
- );
-
- // Turn into regular numbers
- return {
- tokensAvailableInBaseUnits: liquidityInBigNumbers.tokensAvailableInBaseUnits,
- ethValueAvailableInWei: liquidityInBigNumbers.ethValueAvailableInWei,
- };
-};
diff --git a/packages/asset-buyer/src/utils/order_provider_response_processor.ts b/packages/asset-buyer/src/utils/order_provider_response_processor.ts
deleted file mode 100644
index f08cd6150..000000000
--- a/packages/asset-buyer/src/utils/order_provider_response_processor.ts
+++ /dev/null
@@ -1,171 +0,0 @@
-import { OrderAndTraderInfo, OrderStatus, OrderValidatorWrapper } from '@0x/contract-wrappers';
-import { 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 {
- AssetBuyerError,
- OrderProviderRequest,
- OrderProviderResponse,
- OrdersAndFillableAmounts,
- SignedOrderWithRemainingFillableMakerAssetAmount,
-} from '../types';
-
-import { orderUtils } from './order_utils';
-
-export const orderProviderResponseProcessor = {
- throwIfInvalidResponse(response: OrderProviderResponse, request: OrderProviderRequest): void {
- const { makerAssetData, takerAssetData } = request;
- _.forEach(response.orders, order => {
- if (order.makerAssetData !== makerAssetData || order.takerAssetData !== takerAssetData) {
- throw new Error(AssetBuyerError.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 shouldValidateOnChain, attempt to grab fillable amounts from on-chain otherwise assume completely fillable
- * - Sort by rate
- */
- async processAsync(
- orderProviderResponse: OrderProviderResponse,
- isMakerAssetZrxToken: boolean,
- expiryBufferSeconds: number,
- orderValidator?: OrderValidatorWrapper,
- ): Promise<OrdersAndFillableAmounts> {
- // drop orders that are expired or not open
- const filteredOrders = filterOutExpiredAndNonOpenOrders(orderProviderResponse.orders, expiryBufferSeconds);
- // 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 (!_.isUndefined(orderValidator)) {
- const takerAddresses = _.map(filteredOrders, () => constants.NULL_ADDRESS);
- try {
- const ordersAndTradersInfo = await orderValidator.getOrdersAndTradersInfoAsync(
- filteredOrders,
- takerAddresses,
- );
- // 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[],
- expiryBufferSeconds: number,
-): SignedOrderWithRemainingFillableMakerAssetAmount[] {
- const result = _.filter(orders, order => {
- return orderUtils.isOpenOrder(order) && !orderUtils.willOrderExpire(order, expiryBufferSeconds);
- });
- 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: OrderAndTraderInfo[],
- 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 = orderUtils.getRemainingMakerAmount(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-buyer/src/utils/order_utils.ts b/packages/asset-buyer/src/utils/order_utils.ts
deleted file mode 100644
index 3ea3cafd3..000000000
--- a/packages/asset-buyer/src/utils/order_utils.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-
-import { constants } from '../constants';
-
-export const orderUtils = {
- isOrderExpired(order: SignedOrder): boolean {
- return orderUtils.willOrderExpire(order, 0);
- },
- willOrderExpire(order: SignedOrder, secondsFromNow: number): boolean {
- const millisecondsInSecond = 1000;
- const currentUnixTimestampSec = new BigNumber(Date.now() / millisecondsInSecond).integerValue();
- return order.expirationTimeSeconds.isLessThan(currentUnixTimestampSec.plus(secondsFromNow));
- },
- isOpenOrder(order: SignedOrder): boolean {
- return order.takerAddress === constants.NULL_ADDRESS;
- },
- // given a remaining amount of takerAsset, calculate how much makerAsset is available
- getRemainingMakerAmount(order: SignedOrder, remainingTakerAmount: BigNumber): BigNumber {
- const remainingMakerAmount = remainingTakerAmount
- .times(order.makerAssetAmount)
- .div(order.takerAssetAmount)
- .integerValue(BigNumber.ROUND_FLOOR);
- return remainingMakerAmount;
- },
- // given a desired amount of makerAsset, calculate how much takerAsset is required to fill that amount
- getTakerFillAmount(order: SignedOrder, makerFillAmount: BigNumber): BigNumber {
- // Round up because exchange rate favors Maker
- const takerFillAmount = makerFillAmount
- .multipliedBy(order.takerAssetAmount)
- .div(order.makerAssetAmount)
- .integerValue(BigNumber.ROUND_CEIL);
- return takerFillAmount;
- },
- // given a desired amount of takerAsset to fill, calculate how much fee is required by the taker to fill that amount
- getTakerFeeAmount(order: SignedOrder, takerFillAmount: BigNumber): BigNumber {
- // Round down because Taker fee rate favors Taker
- const takerFeeAmount = takerFillAmount
- .multipliedBy(order.takerFee)
- .div(order.takerAssetAmount)
- .integerValue(BigNumber.ROUND_FLOOR);
- return takerFeeAmount;
- },
- // given a desired amount of takerAsset to fill, calculate how much makerAsset will be filled
- getMakerFillAmount(order: SignedOrder, takerFillAmount: BigNumber): BigNumber {
- // Round down because exchange rate favors Maker
- const makerFillAmount = takerFillAmount
- .multipliedBy(order.makerAssetAmount)
- .div(order.takerAssetAmount)
- .integerValue(BigNumber.ROUND_FLOOR);
- return makerFillAmount;
- },
- // given a desired amount of makerAsset, calculate how much fee is required by the maker to fill that amount
- getMakerFeeAmount(order: SignedOrder, makerFillAmount: BigNumber): BigNumber {
- // Round down because Maker fee rate favors Maker
- const makerFeeAmount = makerFillAmount
- .multipliedBy(order.makerFee)
- .div(order.makerAssetAmount)
- .integerValue(BigNumber.ROUND_FLOOR);
- return makerFeeAmount;
- },
- // given a desired amount of ZRX from a fee order, calculate how much takerAsset is required to fill that amount
- // also calculate how much ZRX needs to be bought in order fill the desired amount + takerFee
- getTakerFillAmountForFeeOrder(order: SignedOrder, makerFillAmount: BigNumber): [BigNumber, BigNumber] {
- // For each unit of TakerAsset we buy (MakerAsset - TakerFee)
- const adjustedTakerFillAmount = makerFillAmount
- .multipliedBy(order.takerAssetAmount)
- .div(order.makerAssetAmount.minus(order.takerFee))
- .integerValue(BigNumber.ROUND_CEIL);
- // The amount that we buy will be greater than makerFillAmount, since we buy some amount for fees.
- const adjustedMakerFillAmount = orderUtils.getMakerFillAmount(order, adjustedTakerFillAmount);
- return [adjustedTakerFillAmount, adjustedMakerFillAmount];
- },
-};
diff --git a/packages/asset-buyer/test/asset_buyer_test.ts b/packages/asset-buyer/test/asset_buyer_test.ts
deleted file mode 100644
index f117b4d7a..000000000
--- a/packages/asset-buyer/test/asset_buyer_test.ts
+++ /dev/null
@@ -1,212 +0,0 @@
-import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
-import { Web3ProviderEngine } from '@0x/subproviders';
-import { 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 { AssetBuyer } from '../src';
-import { constants } from '../src/constants';
-import { LiquidityForAssetData, OrderProvider, OrdersAndFillableAmounts } from '../src/types';
-
-import { chaiSetup } from './utils/chai_setup';
-import {
- mockAvailableAssetDatas,
- mockedAssetBuyerWithOrdersAndFillableAmounts,
- orderProviderMock,
-} from './utils/mocks';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-const FAKE_SRA_URL = 'https://fakeurl.com';
-const FAKE_ASSET_DATA = '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48';
-const TOKEN_DECIMALS = 18;
-const DAI_ASSET_DATA = '0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359"';
-const WETH_ASSET_DATA = '0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
-const WETH_DECIMALS = constants.ETHER_TOKEN_DECIMALS;
-
-const baseUnitAmount = (unitAmount: number, decimals = TOKEN_DECIMALS): BigNumber => {
- return Web3Wrapper.toBaseUnitAmount(new BigNumber(unitAmount), decimals);
-};
-
-const expectLiquidityResult = async (
- web3Provider: Web3ProviderEngine,
- orderProvider: OrderProvider,
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
- expectedLiquidityResult: LiquidityForAssetData,
-) => {
- const mockedAssetBuyer = mockedAssetBuyerWithOrdersAndFillableAmounts(
- web3Provider,
- orderProvider,
- FAKE_ASSET_DATA,
- ordersAndFillableAmounts,
- );
- const liquidityResult = await mockedAssetBuyer.object.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA);
- expect(liquidityResult).to.deep.equal(expectedLiquidityResult);
-};
-
-// tslint:disable:custom-no-magic-numbers
-describe('AssetBuyer', () => {
- describe('getLiquidityForAssetDataAsync', () => {
- const mockWeb3Provider = TypeMoq.Mock.ofType(Web3ProviderEngine);
- const mockOrderProvider = orderProviderMock();
-
- beforeEach(() => {
- mockWeb3Provider.reset();
- mockOrderProvider.reset();
- });
-
- afterEach(() => {
- mockWeb3Provider.verifyAll();
- mockOrderProvider.verifyAll();
- });
-
- describe('validation', () => {
- it('should ensure assetData is a string', async () => {
- const assetBuyer = AssetBuyer.getAssetBuyerForStandardRelayerAPIUrl(
- mockWeb3Provider.object,
- FAKE_SRA_URL,
- );
-
- expect(assetBuyer.getLiquidityForAssetDataAsync(false as any)).to.be.rejectedWith(
- 'Expected assetData to be of type string, encountered: false',
- );
- });
- });
-
- describe('asset pair not supported', () => {
- it('should return 0s when no asset pair not supported', async () => {
- mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, []);
-
- const assetBuyer = new AssetBuyer(mockWeb3Provider.object, mockOrderProvider.object);
- const liquidityResult = await assetBuyer.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA);
- expect(liquidityResult).to.deep.equal({
- tokensAvailableInBaseUnits: new BigNumber(0),
- ethValueAvailableInWei: new BigNumber(0),
- });
- });
- it('should return 0s when only other asset pair supported', async () => {
- mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, [DAI_ASSET_DATA]);
-
- const assetBuyer = new AssetBuyer(mockWeb3Provider.object, mockOrderProvider.object);
- const liquidityResult = await assetBuyer.getLiquidityForAssetDataAsync(FAKE_ASSET_DATA);
- expect(liquidityResult).to.deep.equal({
- tokensAvailableInBaseUnits: new BigNumber(0),
- ethValueAvailableInWei: new BigNumber(0),
- });
- });
- });
-
- describe('assetData is supported', () => {
- // orders
- const sellTwoTokensFor1Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({
- makerAssetAmount: baseUnitAmount(2),
- takerAssetAmount: baseUnitAmount(1, WETH_DECIMALS),
- });
- const sellTenTokensFor10Weth: SignedOrder = orderFactory.createSignedOrderFromPartial({
- makerAssetAmount: baseUnitAmount(10),
- takerAssetAmount: baseUnitAmount(10, WETH_DECIMALS),
- });
-
- beforeEach(() => {
- mockAvailableAssetDatas(mockOrderProvider, FAKE_ASSET_DATA, [WETH_ASSET_DATA]);
- });
-
- it('should return 0s when no orders available', async () => {
- const ordersAndFillableAmounts: OrdersAndFillableAmounts = {
- orders: [],
- remainingFillableMakerAssetAmounts: [],
- };
- const expectedResult = {
- tokensAvailableInBaseUnits: new BigNumber(0),
- ethValueAvailableInWei: new BigNumber(0),
- };
- await expectLiquidityResult(
- mockWeb3Provider.object,
- mockOrderProvider.object,
- ordersAndFillableAmounts,
- 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 expectedTokensAvailable = orders[0].makerAssetAmount.plus(orders[1].makerAssetAmount);
- const expectedEthValueAvailable = orders[0].takerAssetAmount.plus(orders[1].takerAssetAmount);
- const expectedResult = {
- tokensAvailableInBaseUnits: expectedTokensAvailable,
- ethValueAvailableInWei: expectedEthValueAvailable,
- };
-
- await expectLiquidityResult(
- mockWeb3Provider.object,
- mockOrderProvider.object,
- ordersAndFillableAmounts,
- expectedResult,
- );
- });
-
- it('should return correct computed value with one partial fillableAmounts', async () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1Weth],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(1)],
- };
- const expectedResult = {
- tokensAvailableInBaseUnits: baseUnitAmount(1),
- ethValueAvailableInWei: baseUnitAmount(0.5, WETH_DECIMALS),
- };
-
- await expectLiquidityResult(
- mockWeb3Provider.object,
- mockOrderProvider.object,
- ordersAndFillableAmounts,
- 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 expectedResult = {
- tokensAvailableInBaseUnits: baseUnitAmount(4),
- ethValueAvailableInWei: baseUnitAmount(3.5, WETH_DECIMALS),
- };
-
- await expectLiquidityResult(
- mockWeb3Provider.object,
- mockOrderProvider.object,
- ordersAndFillableAmounts,
- expectedResult,
- );
- });
-
- it('should return 0s when no amounts fillable', async () => {
- const ordersAndFillableAmounts = {
- orders: [sellTwoTokensFor1Weth, sellTenTokensFor10Weth],
- remainingFillableMakerAssetAmounts: [baseUnitAmount(0), baseUnitAmount(0)],
- };
- const expectedResult = {
- tokensAvailableInBaseUnits: baseUnitAmount(0),
- ethValueAvailableInWei: baseUnitAmount(0, WETH_DECIMALS),
- };
-
- await expectLiquidityResult(
- mockWeb3Provider.object,
- mockOrderProvider.object,
- ordersAndFillableAmounts,
- expectedResult,
- );
- });
- });
- });
-});
diff --git a/packages/asset-buyer/test/buy_quote_calculator_test.ts b/packages/asset-buyer/test/buy_quote_calculator_test.ts
deleted file mode 100644
index 177fd8fe6..000000000
--- a/packages/asset-buyer/test/buy_quote_calculator_test.ts
+++ /dev/null
@@ -1,295 +0,0 @@
-import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import 'mocha';
-
-import { AssetBuyerError, OrdersAndFillableAmounts } from '../src/types';
-import { buyQuoteCalculator } from '../src/utils/buy_quote_calculator';
-
-import { chaiSetup } from './utils/chai_setup';
-import { testHelpers } from './utils/test_helpers';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-// tslint:disable:custom-no-magic-numbers
-describe('buyQuoteCalculator', () => {
- describe('#calculate', () => {
- 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({
- makerAssetAmount: new BigNumber(400),
- takerAssetAmount: new BigNumber(100),
- takerFee: new BigNumber(200),
- });
- firstRemainingFillAmount = new BigNumber(200);
- secondOrder = orderFactory.createSignedOrderFromPartial({
- 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({
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(100),
- });
- smallFeeOrderAndFillableAmount = {
- orders: [smallFeeOrder],
- remainingFillableMakerAssetAmounts: [smallFeeOrder.makerAssetAmount],
- };
- const largeFeeOrder = orderFactory.createSignedOrderFromPartial({
- 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
- const errorFunction = () => {
- buyQuoteCalculator.calculate(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(500),
- 0,
- 0,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(400));
- });
- 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
- const errorFunction = () => {
- buyQuoteCalculator.calculate(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(500),
- 0,
- 0.2,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(333));
- });
- 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
- const errorFunction = () => {
- buyQuoteCalculator.calculate(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(600),
- 0,
- 0.05,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(380));
- });
- it('should throw if not enough maker asset liquidity (partially filled order)', () => {
- const firstOrderAndFillableAmount: OrdersAndFillableAmounts = {
- orders: [firstOrder],
- remainingFillableMakerAssetAmounts: [firstRemainingFillAmount],
- };
-
- const errorFunction = () => {
- buyQuoteCalculator.calculate(
- firstOrderAndFillableAmount,
- smallFeeOrderAndFillableAmount,
- new BigNumber(201),
- 0,
- 0,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(200));
- });
- it('should throw if not enough maker asset liquidity (completely fillable order)', () => {
- const completelyFillableOrder = orderFactory.createSignedOrderFromPartial({
- makerAssetAmount: new BigNumber(123),
- takerAssetAmount: new BigNumber(100),
- takerFee: new BigNumber(200),
- });
- const completelyFillableOrdersAndFillableAmount: OrdersAndFillableAmounts = {
- orders: [completelyFillableOrder],
- remainingFillableMakerAssetAmounts: [completelyFillableOrder.makerAssetAmount],
- };
- const errorFunction = () => {
- buyQuoteCalculator.calculate(
- completelyFillableOrdersAndFillableAmount,
- smallFeeOrderAndFillableAmount,
- new BigNumber(124),
- 0,
- 0,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(123));
- });
- it('should throw with 1 amount available if no slippage', () => {
- const smallOrder = orderFactory.createSignedOrderFromPartial({
- makerAssetAmount: new BigNumber(1),
- takerAssetAmount: new BigNumber(1),
- takerFee: new BigNumber(0),
- });
- const errorFunction = () => {
- buyQuoteCalculator.calculate(
- { orders: [smallOrder], remainingFillableMakerAssetAmounts: [smallOrder.makerAssetAmount] },
- smallFeeOrderAndFillableAmount,
- new BigNumber(600),
- 0,
- 0,
- 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({
- makerAssetAmount: new BigNumber(1),
- takerAssetAmount: new BigNumber(1),
- takerFee: new BigNumber(0),
- });
- const errorFunction = () => {
- buyQuoteCalculator.calculate(
- { orders: [smallOrder], remainingFillableMakerAssetAmounts: [smallOrder.makerAssetAmount] },
- smallFeeOrderAndFillableAmount,
- new BigNumber(600),
- 0,
- 0.2,
- false,
- );
- };
- testHelpers.expectInsufficientLiquidityError(expect, errorFunction, new BigNumber(0));
- });
- });
- it('should not throw if order is fillable', () => {
- expect(() =>
- buyQuoteCalculator.calculate(
- ordersAndFillableAmounts,
- allFeeOrdersAndFillableAmounts,
- new BigNumber(300),
- 0,
- 0,
- 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(() =>
- buyQuoteCalculator.calculate(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- new BigNumber(300),
- 0,
- 0,
- false,
- ),
- ).to.throw(AssetBuyerError.InsufficientZrxLiquidity);
- });
- it('calculates a correct buyQuote 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);
- const feePercentage = 0.02;
- const slippagePercentage = 0;
- const buyQuote = buyQuoteCalculator.calculate(
- ordersAndFillableAmounts,
- smallFeeOrderAndFillableAmount,
- assetBuyAmount,
- feePercentage,
- slippagePercentage,
- false,
- );
- // test if orders are correct
- expect(buyQuote.orders).to.deep.equal([ordersAndFillableAmounts.orders[0]]);
- expect(buyQuote.feeOrders).to.deep.equal([smallFeeOrderAndFillableAmount.orders[0]]);
- // test if rates are correct
- // 50 eth to fill the first order + 100 eth for fees
- const expectedEthAmountForAsset = new BigNumber(50);
- const expectedEthAmountForZrxFees = new BigNumber(100);
- const expectedFillEthAmount = expectedEthAmountForAsset;
- const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.multipliedBy(feePercentage);
- const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees);
- const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
- expect(buyQuote.bestCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
- expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
- expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
- // because we have no slippage protection, minRate is equal to maxRate
- expect(buyQuote.worstCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
- expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
- expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
- // test if feePercentage gets passed through
- expect(buyQuote.feePercentage).to.equal(feePercentage);
- });
- it('calculates a correct buyQuote with 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);
- const feePercentage = 0.02;
- const slippagePercentage = 0.5;
- const buyQuote = buyQuoteCalculator.calculate(
- ordersAndFillableAmounts,
- allFeeOrdersAndFillableAmounts,
- assetBuyAmount,
- feePercentage,
- slippagePercentage,
- false,
- );
- // test if orders are correct
- expect(buyQuote.orders).to.deep.equal(ordersAndFillableAmounts.orders);
- expect(buyQuote.feeOrders).to.deep.equal(allFeeOrdersAndFillableAmounts.orders);
- // test if rates are correct
- // 50 eth to fill the first order + 100 eth for fees
- const expectedEthAmountForAsset = new BigNumber(50);
- const expectedEthAmountForZrxFees = new BigNumber(100);
- const expectedFillEthAmount = expectedEthAmountForAsset;
- const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.multipliedBy(feePercentage);
- const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees);
- const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
- expect(buyQuote.bestCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
- expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
- expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
- // 100 eth to fill the first order + 208 eth for fees
- const expectedWorstEthAmountForAsset = new BigNumber(100);
- const expectedWorstEthAmountForZrxFees = new BigNumber(208);
- const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset;
- const expectedWorstAffiliateFeeEthAmount = expectedWorstEthAmountForAsset.multipliedBy(feePercentage);
- const expectedWorstFeeEthAmount = expectedWorstAffiliateFeeEthAmount.plus(expectedWorstEthAmountForZrxFees);
- const expectedWorstTotalEthAmount = expectedWorstFillEthAmount.plus(expectedWorstFeeEthAmount);
- expect(buyQuote.worstCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedWorstFillEthAmount);
- expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedWorstFeeEthAmount);
- expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedWorstTotalEthAmount);
- // test if feePercentage gets passed through
- expect(buyQuote.feePercentage).to.equal(feePercentage);
- });
- });
-});
diff --git a/packages/asset-buyer/test/utils/chai_setup.ts b/packages/asset-buyer/test/utils/chai_setup.ts
deleted file mode 100644
index 1a8733093..000000000
--- a/packages/asset-buyer/test/utils/chai_setup.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as chai from 'chai';
-import chaiAsPromised = require('chai-as-promised');
-import ChaiBigNumber = require('chai-bignumber');
-import * as dirtyChai from 'dirty-chai';
-
-export const chaiSetup = {
- configure(): void {
- chai.config.includeStack = true;
- chai.use(ChaiBigNumber());
- chai.use(dirtyChai);
- chai.use(chaiAsPromised);
- },
-};
diff --git a/packages/asset-buyer/test/utils/mocks.ts b/packages/asset-buyer/test/utils/mocks.ts
deleted file mode 100644
index d3e1c09c4..000000000
--- a/packages/asset-buyer/test/utils/mocks.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { Web3ProviderEngine } from '@0x/subproviders';
-import * as TypeMoq from 'typemoq';
-
-import { AssetBuyer } from '../../src/asset_buyer';
-import { OrderProvider, OrderProviderResponse, OrdersAndFillableAmounts } from '../../src/types';
-
-// tslint:disable:promise-function-async
-
-// Implementing dummy class for using in mocks, see https://github.com/florinn/typemoq/issues/3
-class OrderProviderClass implements OrderProvider {
- // tslint:disable-next-line:prefer-function-over-method
- public async getOrdersAsync(): Promise<OrderProviderResponse> {
- return Promise.resolve({ orders: [] });
- }
- // tslint:disable-next-line:prefer-function-over-method
- public async getAvailableMakerAssetDatasAsync(takerAssetData: string): Promise<string[]> {
- return Promise.resolve([]);
- }
-}
-
-export const orderProviderMock = () => {
- return TypeMoq.Mock.ofType(OrderProviderClass, TypeMoq.MockBehavior.Strict);
-};
-
-export const mockAvailableAssetDatas = (
- mockOrderProvider: TypeMoq.IMock<OrderProviderClass>,
- assetData: string,
- availableAssetDatas: string[],
-) => {
- mockOrderProvider
- .setup(op => op.getAvailableMakerAssetDatasAsync(TypeMoq.It.isValue(assetData)))
- .returns(() => {
- return Promise.resolve(availableAssetDatas);
- })
- .verifiable(TypeMoq.Times.once());
-};
-
-const partiallyMockedAssetBuyer = (
- provider: Web3ProviderEngine,
- orderProvider: OrderProvider,
-): TypeMoq.IMock<AssetBuyer> => {
- const rawAssetBuyer = new AssetBuyer(provider, orderProvider);
- const mockedAssetBuyer = TypeMoq.Mock.ofInstance(rawAssetBuyer, TypeMoq.MockBehavior.Loose, false);
- mockedAssetBuyer.callBase = true;
- return mockedAssetBuyer;
-};
-
-const mockGetOrdersAndAvailableAmounts = (
- mockedAssetBuyer: TypeMoq.IMock<AssetBuyer>,
- assetData: string,
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
-): void => {
- mockedAssetBuyer
- .setup(a => a.getOrdersAndFillableAmountsAsync(assetData, false))
- .returns(() => Promise.resolve(ordersAndFillableAmounts))
- .verifiable(TypeMoq.Times.once());
-};
-
-export const mockedAssetBuyerWithOrdersAndFillableAmounts = (
- provider: Web3ProviderEngine,
- orderProvider: OrderProvider,
- assetData: string,
- ordersAndFillableAmounts: OrdersAndFillableAmounts,
-): TypeMoq.IMock<AssetBuyer> => {
- const mockedAssetBuyer = partiallyMockedAssetBuyer(provider, orderProvider);
- mockGetOrdersAndAvailableAmounts(mockedAssetBuyer, assetData, ordersAndFillableAmounts);
- return mockedAssetBuyer;
-};
diff --git a/packages/asset-buyer/test/utils/test_helpers.ts b/packages/asset-buyer/test/utils/test_helpers.ts
deleted file mode 100644
index 04a58d2c8..000000000
--- a/packages/asset-buyer/test/utils/test_helpers.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { BigNumber } from '@0x/utils';
-
-import { InsufficientAssetLiquidityError } from '../../src/errors';
-
-export const testHelpers = {
- expectInsufficientLiquidityError: (
- expect: Chai.ExpectStatic,
- functionWhichTriggersError: () => void,
- expectedAmountAvailableToFill: BigNumber,
- ): void => {
- let wasErrorThrown = false;
- try {
- functionWhichTriggersError();
- } catch (e) {
- wasErrorThrown = true;
- expect(e).to.be.instanceOf(InsufficientAssetLiquidityError);
- if (expectedAmountAvailableToFill) {
- expect(e.amountAvailableToFill).to.be.bignumber.equal(expectedAmountAvailableToFill);
- } else {
- expect(e.amountAvailableToFill).to.be.undefined();
- }
- }
-
- expect(wasErrorThrown).to.be.true();
- },
-};
diff --git a/packages/asset-buyer/tsconfig.json b/packages/asset-buyer/tsconfig.json
deleted file mode 100644
index 2ee711adc..000000000
--- a/packages/asset-buyer/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "../../tsconfig",
- "compilerOptions": {
- "outDir": "lib",
- "rootDir": "."
- },
- "include": ["./src/**/*", "./test/**/*"]
-}
diff --git a/packages/asset-buyer/tslint.json b/packages/asset-buyer/tslint.json
deleted file mode 100644
index dd9053357..000000000
--- a/packages/asset-buyer/tslint.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": ["@0x/tslint-config"]
-}
diff --git a/packages/asset-buyer/typedoc-tsconfig.json b/packages/asset-buyer/typedoc-tsconfig.json
deleted file mode 100644
index c9b0af1ae..000000000
--- a/packages/asset-buyer/typedoc-tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../typedoc-tsconfig",
- "compilerOptions": {
- "outDir": "lib"
- },
- "include": ["./src/**/*", "./test/**/*"]
-}