aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/asset-buyer/package.json2
-rw-r--r--packages/asset-buyer/src/asset_buyers/asset_buyer.ts129
-rw-r--r--packages/asset-buyer/src/constants.ts1
-rw-r--r--packages/asset-buyer/src/forwarder_helper_factory.ts510
-rw-r--r--packages/asset-buyer/src/forwarder_helper_impl.ts64
-rw-r--r--packages/asset-buyer/src/index.ts4
-rw-r--r--packages/asset-buyer/src/types.ts63
-rw-r--r--packages/asset-buyer/src/utils/forwarder_helper_impl_config_utils.ts170
-rw-r--r--packages/asset-buyer/test/forwarder_helper_impl_test.ts264
-rw-r--r--tsconfig.json2
10 files changed, 635 insertions, 574 deletions
diff --git a/packages/asset-buyer/package.json b/packages/asset-buyer/package.json
index e4d3d0701..0d6d1f52b 100644
--- a/packages/asset-buyer/package.json
+++ b/packages/asset-buyer/package.json
@@ -48,6 +48,8 @@
"@0xproject/types": "^1.0.1",
"@0xproject/typescript-typings": "^2.0.0",
"@0xproject/utils": "^1.0.8",
+ "@0xproject/web3-wrapper": "^2.0.2",
+ "ethereum-types": "^1.0.6",
"lodash": "^4.17.10"
},
"devDependencies": {
diff --git a/packages/asset-buyer/src/asset_buyers/asset_buyer.ts b/packages/asset-buyer/src/asset_buyers/asset_buyer.ts
new file mode 100644
index 000000000..eb7f85e2b
--- /dev/null
+++ b/packages/asset-buyer/src/asset_buyers/asset_buyer.ts
@@ -0,0 +1,129 @@
+import { ContractWrappers } from '@0xproject/contract-wrappers';
+import { marketUtils } from '@0xproject/order-utils';
+import { SignedOrder } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import * as _ from 'lodash';
+import { Provider } from 'ethereum-types';
+
+import { constants } from '../constants';
+import { AssetBuyerError, BuyQuote, BuyQuoteRequest } from '../types';
+
+const SLIPPAGE_PERCENTAGE = new BigNumber(0.2); // 20% slippage protection, possibly move this into request interface
+
+export interface AssetBuyerConfig {
+ orders: SignedOrder[];
+ feeOrders: SignedOrder[];
+ remainingFillableMakerAssetAmounts?: BigNumber[];
+ remainingFillableFeeAmounts?: BigNumber[];
+ networkId?: number;
+}
+
+export class AssetBuyer {
+ public readonly provider: Provider;
+ public readonly config: AssetBuyerConfig;
+ private _contractWrappers: ContractWrappers;
+ constructor(provider: Provider, config: AssetBuyerConfig) {
+ this.provider = provider;
+ this.config = config;
+ const networkId = this.config.networkId || constants.MAINNET_NETWORK_ID;
+ this._contractWrappers = new ContractWrappers(this.provider, {
+ networkId,
+ });
+ }
+ /**
+ * Given a BuyQuoteRequest, returns a BuyQuote containing all information relevant to fulfilling the buy. Pass the BuyQuote
+ * to executeBuyQuoteAsync to execute the buy.
+ * @param buyQuoteRequest An object that conforms to BuyQuoteRequest. See type definition for more information.
+ * @return An object that conforms to BuyQuote that satisfies the request. See type definition for more information.
+ */
+ public getBuyQuote(buyQuoteRequest: BuyQuoteRequest): BuyQuote {
+ const { assetBuyAmount, feePercentage } = buyQuoteRequest;
+ const { orders, feeOrders, remainingFillableMakerAssetAmounts, remainingFillableFeeAmounts } = this.config;
+ // TODO: optimization
+ // make the slippage percentage customizable
+ const slippageBufferAmount = assetBuyAmount.mul(SLIPPAGE_PERCENTAGE).round();
+ const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
+ orders,
+ assetBuyAmount,
+ {
+ remainingFillableMakerAssetAmounts,
+ slippageBufferAmount,
+ },
+ );
+ if (remainingFillAmount.gt(constants.ZERO_AMOUNT)) {
+ throw new Error(AssetBuyerError.InsufficientAssetLiquidity);
+ }
+ // TODO: 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
+ const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
+ resultOrders,
+ feeOrders,
+ {
+ remainingFillableMakerAssetAmounts,
+ remainingFillableFeeAmounts,
+ },
+ );
+ if (remainingFeeAmount.gt(constants.ZERO_AMOUNT)) {
+ throw new Error(AssetBuyerError.InsufficientZrxLiquidity);
+ }
+ const assetData = orders[0].makerAssetData;
+ // TODO: critical
+ // calculate minRate and maxRate by calculating min and max eth usage and then dividing into
+ // assetBuyAmount to get assetData / WETH
+ return {
+ assetData,
+ orders: resultOrders,
+ feeOrders: resultFeeOrders,
+ minRate: constants.ZERO_AMOUNT,
+ maxRate: constants.ZERO_AMOUNT,
+ assetBuyAmount,
+ feePercentage,
+ };
+ }
+ /**
+ * 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 rate The desired rate to execute the buy at. Affects the amount of ETH sent with the transaction, defaults to buyQuote.maxRate.
+ * @param takerAddress The address to perform the buy. Defaults to the first available address from the provider.
+ * @param feeRecipient The address where affiliate fees are sent. Defaults to null address (0x000...000).
+ * @return A promise of the txHash.
+ */
+ public async executeBuyQuoteAsync(
+ buyQuote: BuyQuote,
+ rate?: BigNumber,
+ takerAddress?: string,
+ feeRecipient: string = constants.NULL_ADDRESS,
+ ): Promise<string> {
+ const { orders, feeOrders, feePercentage, assetBuyAmount, maxRate } = 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);
+ }
+ }
+ // if no rate is provided, default to the maxRate from buyQuote
+ const desiredRate = rate || maxRate;
+ // calculate how much eth is required to buy assetBuyAmount at the desired rate
+ const ethAmount = assetBuyAmount.dividedToIntegerBy(desiredRate);
+ const txHash = await this._contractWrappers.forwarder.marketBuyOrdersWithEthAsync(
+ orders,
+ assetBuyAmount,
+ finalTakerAddress,
+ ethAmount,
+ feeOrders,
+ feePercentage,
+ feeRecipient,
+ );
+ return txHash;
+ }
+}
diff --git a/packages/asset-buyer/src/constants.ts b/packages/asset-buyer/src/constants.ts
index c0a1b090e..5785e705b 100644
--- a/packages/asset-buyer/src/constants.ts
+++ b/packages/asset-buyer/src/constants.ts
@@ -3,4 +3,5 @@ import { BigNumber } from '@0xproject/utils';
export const constants = {
ZERO_AMOUNT: new BigNumber(0),
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
+ MAINNET_NETWORK_ID: 1,
};
diff --git a/packages/asset-buyer/src/forwarder_helper_factory.ts b/packages/asset-buyer/src/forwarder_helper_factory.ts
index 2b37ac98f..9a3832e81 100644
--- a/packages/asset-buyer/src/forwarder_helper_factory.ts
+++ b/packages/asset-buyer/src/forwarder_helper_factory.ts
@@ -1,261 +1,261 @@
-import { assert } from '@0xproject/assert';
-import { APIOrder, HttpClient, OrderbookResponse } from '@0xproject/connect';
-import { ContractWrappers, OrderAndTraderInfo, OrderStatus } from '@0xproject/contract-wrappers';
-import { schemas } from '@0xproject/json-schemas';
-import { assetDataUtils } from '@0xproject/order-utils';
-import { RemainingFillableCalculator } from '@0xproject/order-utils/lib/src/remaining_fillable_calculator';
-import { RPCSubprovider, Web3ProviderEngine } from '@0xproject/subproviders';
-import { SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
+// import { assert } from '@0xproject/assert';
+// import { APIOrder, HttpClient, OrderbookResponse } from '@0xproject/connect';
+// import { ContractWrappers, OrderAndTraderInfo, OrderStatus } from '@0xproject/contract-wrappers';
+// import { schemas } from '@0xproject/json-schemas';
+// import { assetDataUtils } from '@0xproject/order-utils';
+// import { RemainingFillableCalculator } from '@0xproject/order-utils/lib/src/remaining_fillable_calculator';
+// import { RPCSubprovider, Web3ProviderEngine } from '@0xproject/subproviders';
+// import { SignedOrder } from '@0xproject/types';
+// import { BigNumber } from '@0xproject/utils';
+// import * as _ from 'lodash';
-import { constants } from './constants';
-import { ForwarderHelperImpl, ForwarderHelperImplConfig } from './forwarder_helper_impl';
-import { ForwarderHelper, ForwarderHelperFactoryError } from './types';
-import { orderUtils } from './utils/order_utils';
+// import { constants } from './constants';
+// import { ForwarderHelperImpl, ForwarderHelperImplConfig } from '@0xproject/asset-buyer/src/asset_buyer';
+// import { ForwarderHelper, ForwarderHelperFactoryError } from './types';
+// import { orderUtils } from './utils/order_utils';
-export const forwarderHelperFactory = {
- /**
- * Given an array of orders and an array of feeOrders, get a ForwarderHelper
- * @param orders An array of objects conforming to SignedOrder. Each order should specify the same makerAssetData and takerAssetData
- * @param feeOrders An array of objects conforming to SignedOrder. Each order should specify ZRX as makerAssetData WETH as takerAssetData
- * @return A ForwarderHelper, see type for definition
- */
- getForwarderHelperForOrders(orders: SignedOrder[], feeOrders: SignedOrder[] = []): ForwarderHelper {
- assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
- assert.doesConformToSchema('feeOrders', orders, schemas.signedOrdersSchema);
- // TODO: Add assertion here for orders all having the same makerAsset and takerAsset
- const config: ForwarderHelperImplConfig = {
- orders,
- feeOrders,
- };
- const helper = new ForwarderHelperImpl(config);
- return helper;
- },
- /**
- * Given a desired makerAsset and SRA url, get a ForwarderHelper
- * @param makerAssetData An array of objects conforming to SignedOrder. Each order should specify the same makerAssetData and takerAssetData
- * @param sraUrl A url pointing to an SRA v2 compliant endpoint.
- * @param rpcUrl A url pointing to an ethereum node.
- * @param networkId The ethereum networkId, defaults to 1 (mainnet).
- * @return A ForwarderHelper, see type for definition
- */
- async getForwarderHelperForMakerAssetDataAsync(
- makerAssetData: string,
- sraUrl: string,
- rpcUrl?: string,
- networkId: number = 1,
- ): Promise<ForwarderHelper> {
- assert.isHexString('makerAssetData', makerAssetData);
- assert.isWebUri('sraUrl', sraUrl);
- if (!_.isUndefined(rpcUrl)) {
- assert.isWebUri('rpcUrl', rpcUrl);
- }
- assert.isNumber('networkId', networkId);
- // create provider
- const providerEngine = new Web3ProviderEngine();
- if (!_.isUndefined(rpcUrl)) {
- providerEngine.addProvider(new RPCSubprovider(rpcUrl));
- }
- providerEngine.start();
- // create contract wrappers given provider and networkId
- const contractWrappers = new ContractWrappers(providerEngine, { networkId });
- // find ether token asset data
- const etherTokenAddressIfExists = contractWrappers.etherToken.getContractAddressIfExists();
- if (_.isUndefined(etherTokenAddressIfExists)) {
- throw new Error(ForwarderHelperFactoryError.NoEtherTokenContractFound);
- }
- const etherTokenAssetData = assetDataUtils.encodeERC20AssetData(etherTokenAddressIfExists);
- // find zrx token asset data
- let zrxTokenAssetData: string;
- try {
- zrxTokenAssetData = contractWrappers.exchange.getZRXAssetData();
- } catch (err) {
- throw new Error(ForwarderHelperFactoryError.NoZrxTokenContractFound);
- }
- // get orderbooks for makerAsset/WETH and ZRX/WETH
- const sraClient = new HttpClient(sraUrl);
- const orderbookRequests = [
- { baseAssetData: makerAssetData, quoteAssetData: etherTokenAssetData },
- { baseAssetData: zrxTokenAssetData, quoteAssetData: etherTokenAssetData },
- ];
- const requestOpts = { networkId };
- let makerAssetOrderbook: OrderbookResponse;
- let zrxOrderbook: OrderbookResponse;
- try {
- [makerAssetOrderbook, zrxOrderbook] = await Promise.all(
- _.map(orderbookRequests, request => sraClient.getOrderbookAsync(request, requestOpts)),
- );
- } catch (err) {
- throw new Error(ForwarderHelperFactoryError.StandardRelayerApiError);
- }
- // validate orders and find remaining fillable from on chain state or sra api
- let ordersAndRemainingFillableMakerAssetAmounts: OrdersAndRemainingFillableMakerAssetAmounts;
- let feeOrdersAndRemainingFillableMakerAssetAmounts: OrdersAndRemainingFillableMakerAssetAmounts;
- if (!_.isUndefined(rpcUrl)) {
- // if we do have an rpc url, get on-chain orders and traders info via the OrderValidatorWrapper
- const ordersFromSra = getOpenAsksFromOrderbook(makerAssetOrderbook);
- const feeOrdersFromSra = getOpenAsksFromOrderbook(zrxOrderbook);
- // TODO: try catch these requests and throw a more domain specific error
- // TODO: optimization, reduce this to once RPC call buy combining orders into one array and then splitting up the response
- const [makerAssetOrdersAndTradersInfo, feeOrdersAndTradersInfo] = await Promise.all(
- _.map([ordersFromSra, feeOrdersFromSra], ordersToBeValidated => {
- const takerAddresses = _.map(ordersToBeValidated, () => constants.NULL_ADDRESS);
- return contractWrappers.orderValidator.getOrdersAndTradersInfoAsync(
- ordersToBeValidated,
- takerAddresses,
- );
- }),
- );
- // take maker asset orders from SRA + on chain information and find the valid orders and remaining fillable maker asset amounts
- ordersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
- ordersFromSra,
- makerAssetOrdersAndTradersInfo,
- zrxTokenAssetData,
- );
- // take fee orders from SRA + on chain information and find the valid orders and remaining fillable maker asset amounts
- feeOrdersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
- feeOrdersFromSra,
- feeOrdersAndTradersInfo,
- zrxTokenAssetData,
- );
- } else {
- // if we don't have an rpc url, assume all orders are valid and fallback to optional fill amounts from SRA
- // if fill amounts are not available from the SRA, assume all orders are completely fillable
- const apiOrdersFromSra = makerAssetOrderbook.asks.records;
- const feeApiOrdersFromSra = zrxOrderbook.asks.records;
- // take maker asset orders from SRA and the valid orders and remaining fillable maker asset amounts
- ordersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
- apiOrdersFromSra,
- );
- // take fee orders from SRA and find the valid orders and remaining fillable maker asset amounts
- feeOrdersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
- feeApiOrdersFromSra,
- );
- }
- // compile final config
- const config: ForwarderHelperImplConfig = {
- orders: ordersAndRemainingFillableMakerAssetAmounts.orders,
- feeOrders: feeOrdersAndRemainingFillableMakerAssetAmounts.orders,
- remainingFillableMakerAssetAmounts:
- ordersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
- remainingFillableFeeAmounts:
- feeOrdersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
- };
- const helper = new ForwarderHelperImpl(config);
- return helper;
- },
-};
+// export const forwarderHelperFactory = {
+// /**
+// * Given an array of orders and an array of feeOrders, get a ForwarderHelper
+// * @param orders An array of objects conforming to SignedOrder. Each order should specify the same makerAssetData and takerAssetData
+// * @param feeOrders An array of objects conforming to SignedOrder. Each order should specify ZRX as makerAssetData WETH as takerAssetData
+// * @return A ForwarderHelper, see type for definition
+// */
+// getForwarderHelperForOrders(orders: SignedOrder[], feeOrders: SignedOrder[] = []): ForwarderHelper {
+// assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
+// assert.doesConformToSchema('feeOrders', orders, schemas.signedOrdersSchema);
+// // TODO: Add assertion here for orders all having the same makerAsset and takerAsset
+// const config: ForwarderHelperImplConfig = {
+// orders,
+// feeOrders,
+// };
+// const helper = new ForwarderHelperImpl(config);
+// return helper;
+// },
+// /**
+// * Given a desired makerAsset and SRA url, get a ForwarderHelper
+// * @param makerAssetData An array of objects conforming to SignedOrder. Each order should specify the same makerAssetData and takerAssetData
+// * @param sraUrl A url pointing to an SRA v2 compliant endpoint.
+// * @param rpcUrl A url pointing to an ethereum node.
+// * @param networkId The ethereum networkId, defaults to 1 (mainnet).
+// * @return A ForwarderHelper, see type for definition
+// */
+// async getForwarderHelperForMakerAssetDataAsync(
+// makerAssetData: string,
+// sraUrl: string,
+// rpcUrl?: string,
+// networkId: number = 1,
+// ): Promise<ForwarderHelper> {
+// assert.isHexString('makerAssetData', makerAssetData);
+// assert.isWebUri('sraUrl', sraUrl);
+// if (!_.isUndefined(rpcUrl)) {
+// assert.isWebUri('rpcUrl', rpcUrl);
+// }
+// assert.isNumber('networkId', networkId);
+// // create provider
+// const providerEngine = new Web3ProviderEngine();
+// if (!_.isUndefined(rpcUrl)) {
+// providerEngine.addProvider(new RPCSubprovider(rpcUrl));
+// }
+// providerEngine.start();
+// // create contract wrappers given provider and networkId
+// const contractWrappers = new ContractWrappers(providerEngine, { networkId });
+// // find ether token asset data
+// const etherTokenAddressIfExists = contractWrappers.etherToken.getContractAddressIfExists();
+// if (_.isUndefined(etherTokenAddressIfExists)) {
+// throw new Error(ForwarderHelperFactoryError.NoEtherTokenContractFound);
+// }
+// const etherTokenAssetData = assetDataUtils.encodeERC20AssetData(etherTokenAddressIfExists);
+// // find zrx token asset data
+// let zrxTokenAssetData: string;
+// try {
+// zrxTokenAssetData = contractWrappers.exchange.getZRXAssetData();
+// } catch (err) {
+// throw new Error(ForwarderHelperFactoryError.NoZrxTokenContractFound);
+// }
+// // get orderbooks for makerAsset/WETH and ZRX/WETH
+// const sraClient = new HttpClient(sraUrl);
+// const orderbookRequests = [
+// { baseAssetData: makerAssetData, quoteAssetData: etherTokenAssetData },
+// { baseAssetData: zrxTokenAssetData, quoteAssetData: etherTokenAssetData },
+// ];
+// const requestOpts = { networkId };
+// let makerAssetOrderbook: OrderbookResponse;
+// let zrxOrderbook: OrderbookResponse;
+// try {
+// [makerAssetOrderbook, zrxOrderbook] = await Promise.all(
+// _.map(orderbookRequests, request => sraClient.getOrderbookAsync(request, requestOpts)),
+// );
+// } catch (err) {
+// throw new Error(ForwarderHelperFactoryError.StandardRelayerApiError);
+// }
+// // validate orders and find remaining fillable from on chain state or sra api
+// let ordersAndRemainingFillableMakerAssetAmounts: OrdersAndRemainingFillableMakerAssetAmounts;
+// let feeOrdersAndRemainingFillableMakerAssetAmounts: OrdersAndRemainingFillableMakerAssetAmounts;
+// if (!_.isUndefined(rpcUrl)) {
+// // if we do have an rpc url, get on-chain orders and traders info via the OrderValidatorWrapper
+// const ordersFromSra = getOpenAsksFromOrderbook(makerAssetOrderbook);
+// const feeOrdersFromSra = getOpenAsksFromOrderbook(zrxOrderbook);
+// // TODO: try catch these requests and throw a more domain specific error
+// // TODO: optimization, reduce this to once RPC call buy combining orders into one array and then splitting up the response
+// const [makerAssetOrdersAndTradersInfo, feeOrdersAndTradersInfo] = await Promise.all(
+// _.map([ordersFromSra, feeOrdersFromSra], ordersToBeValidated => {
+// const takerAddresses = _.map(ordersToBeValidated, () => constants.NULL_ADDRESS);
+// return contractWrappers.orderValidator.getOrdersAndTradersInfoAsync(
+// ordersToBeValidated,
+// takerAddresses,
+// );
+// }),
+// );
+// // take maker asset orders from SRA + on chain information and find the valid orders and remaining fillable maker asset amounts
+// ordersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
+// ordersFromSra,
+// makerAssetOrdersAndTradersInfo,
+// zrxTokenAssetData,
+// );
+// // take fee orders from SRA + on chain information and find the valid orders and remaining fillable maker asset amounts
+// feeOrdersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
+// feeOrdersFromSra,
+// feeOrdersAndTradersInfo,
+// zrxTokenAssetData,
+// );
+// } else {
+// // if we don't have an rpc url, assume all orders are valid and fallback to optional fill amounts from SRA
+// // if fill amounts are not available from the SRA, assume all orders are completely fillable
+// const apiOrdersFromSra = makerAssetOrderbook.asks.records;
+// const feeApiOrdersFromSra = zrxOrderbook.asks.records;
+// // take maker asset orders from SRA and the valid orders and remaining fillable maker asset amounts
+// ordersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
+// apiOrdersFromSra,
+// );
+// // take fee orders from SRA and find the valid orders and remaining fillable maker asset amounts
+// feeOrdersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
+// feeApiOrdersFromSra,
+// );
+// }
+// // compile final config
+// const config: ForwarderHelperImplConfig = {
+// orders: ordersAndRemainingFillableMakerAssetAmounts.orders,
+// feeOrders: feeOrdersAndRemainingFillableMakerAssetAmounts.orders,
+// remainingFillableMakerAssetAmounts:
+// ordersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
+// remainingFillableFeeAmounts:
+// feeOrdersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
+// };
+// const helper = new ForwarderHelperImpl(config);
+// return helper;
+// },
+// };
-interface OrdersAndRemainingFillableMakerAssetAmounts {
- orders: SignedOrder[];
- remainingFillableMakerAssetAmounts: BigNumber[];
-}
+// interface OrdersAndRemainingFillableMakerAssetAmounts {
+// orders: SignedOrder[];
+// remainingFillableMakerAssetAmounts: BigNumber[];
+// }
-/**
- * Given an array of APIOrder objects from a standard relayer api, return an array
- * of fillable orders with their corresponding remainingFillableMakerAssetAmounts
- */
-function getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
- apiOrders: APIOrder[],
-): OrdersAndRemainingFillableMakerAssetAmounts {
- const result = _.reduce(
- apiOrders,
- (acc, apiOrder) => {
- // get current accumulations
- const { orders, remainingFillableMakerAssetAmounts } = acc;
- // get order and metadata
- const { order, metaData } = apiOrder;
- // if the order is expired or not open, move on
- if (orderUtils.isOrderExpired(order) || !orderUtils.isOpenOrder(order)) {
- return acc;
- }
- // calculate remainingFillableMakerAssetAmount from api metadata, else assume order is completely fillable
- const remainingFillableTakerAssetAmount = _.get(
- metaData,
- 'remainingTakerAssetAmount',
- order.takerAssetAmount,
- );
- const remainingFillableMakerAssetAmount = orderUtils.calculateRemainingMakerAssetAmount(
- order,
- remainingFillableTakerAssetAmount,
- );
- // if there is some amount of maker asset left to fill and add the order and remaining amount to the accumulations
- // if there is not any maker asset left to fill, do not add
- if (remainingFillableMakerAssetAmount.gt(constants.ZERO_AMOUNT)) {
- return {
- orders: _.concat(orders, order),
- remainingFillableMakerAssetAmounts: _.concat(
- remainingFillableMakerAssetAmounts,
- remainingFillableMakerAssetAmount,
- ),
- };
- } else {
- return acc;
- }
- },
- { orders: [] as SignedOrder[], remainingFillableMakerAssetAmounts: [] as BigNumber[] },
- );
- return result;
-}
+// /**
+// * Given an array of APIOrder objects from a standard relayer api, return an array
+// * of fillable orders with their corresponding remainingFillableMakerAssetAmounts
+// */
+// function getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
+// apiOrders: APIOrder[],
+// ): OrdersAndRemainingFillableMakerAssetAmounts {
+// const result = _.reduce(
+// apiOrders,
+// (acc, apiOrder) => {
+// // get current accumulations
+// const { orders, remainingFillableMakerAssetAmounts } = acc;
+// // get order and metadata
+// const { order, metaData } = apiOrder;
+// // if the order is expired or not open, move on
+// if (orderUtils.isOrderExpired(order) || !orderUtils.isOpenOrder(order)) {
+// return acc;
+// }
+// // calculate remainingFillableMakerAssetAmount from api metadata, else assume order is completely fillable
+// const remainingFillableTakerAssetAmount = _.get(
+// metaData,
+// 'remainingTakerAssetAmount',
+// order.takerAssetAmount,
+// );
+// const remainingFillableMakerAssetAmount = orderUtils.calculateRemainingMakerAssetAmount(
+// order,
+// remainingFillableTakerAssetAmount,
+// );
+// // if there is some amount of maker asset left to fill and add the order and remaining amount to the accumulations
+// // if there is not any maker asset left to fill, do not add
+// if (remainingFillableMakerAssetAmount.gt(constants.ZERO_AMOUNT)) {
+// return {
+// orders: _.concat(orders, order),
+// remainingFillableMakerAssetAmounts: _.concat(
+// remainingFillableMakerAssetAmounts,
+// remainingFillableMakerAssetAmount,
+// ),
+// };
+// } else {
+// return acc;
+// }
+// },
+// { orders: [] as SignedOrder[], remainingFillableMakerAssetAmounts: [] as BigNumber[] },
+// );
+// 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 getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
- inputOrders: SignedOrder[],
- ordersAndTradersInfo: OrderAndTraderInfo[],
- zrxAssetData: string,
-): OrdersAndRemainingFillableMakerAssetAmounts {
- // 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,
- (acc, order, index) => {
- // get current accumulations
- const { orders, remainingFillableMakerAssetAmounts } = acc;
- // 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 acc;
- }
- // 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.calculateRemainingMakerAssetAmount(
- order,
- remainingTakerAssetAmount,
- );
- const remainingFillableCalculator = new RemainingFillableCalculator(
- order.makerFee,
- order.makerAssetAmount,
- order.makerAssetData === zrxAssetData,
- transferrableAssetAmount,
- transferrableFeeAssetAmount,
- remainingMakerAssetAmount,
- );
- const remainingFillableAmount = remainingFillableCalculator.computeRemainingFillable();
- return {
- orders: _.concat(orders, order),
- remainingFillableMakerAssetAmounts: _.concat(
- remainingFillableMakerAssetAmounts,
- remainingFillableAmount,
- ),
- };
- },
- { orders: [] as SignedOrder[], remainingFillableMakerAssetAmounts: [] as BigNumber[] },
- );
- 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 getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
+// inputOrders: SignedOrder[],
+// ordersAndTradersInfo: OrderAndTraderInfo[],
+// zrxAssetData: string,
+// ): OrdersAndRemainingFillableMakerAssetAmounts {
+// // 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,
+// (acc, order, index) => {
+// // get current accumulations
+// const { orders, remainingFillableMakerAssetAmounts } = acc;
+// // 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 acc;
+// }
+// // 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.calculateRemainingMakerAssetAmount(
+// order,
+// remainingTakerAssetAmount,
+// );
+// const remainingFillableCalculator = new RemainingFillableCalculator(
+// order.makerFee,
+// order.makerAssetAmount,
+// order.makerAssetData === zrxAssetData,
+// transferrableAssetAmount,
+// transferrableFeeAssetAmount,
+// remainingMakerAssetAmount,
+// );
+// const remainingFillableAmount = remainingFillableCalculator.computeRemainingFillable();
+// return {
+// orders: _.concat(orders, order),
+// remainingFillableMakerAssetAmounts: _.concat(
+// remainingFillableMakerAssetAmounts,
+// remainingFillableAmount,
+// ),
+// };
+// },
+// { orders: [] as SignedOrder[], remainingFillableMakerAssetAmounts: [] as BigNumber[] },
+// );
+// return result;
+// }
-function getOpenAsksFromOrderbook(orderbookResponse: OrderbookResponse): SignedOrder[] {
- const asks = _.map(orderbookResponse.asks.records, apiOrder => apiOrder.order);
- const result = _.filter(asks, ask => orderUtils.isOpenOrder(ask));
- return result;
-}
+// function getOpenAsksFromOrderbook(orderbookResponse: OrderbookResponse): SignedOrder[] {
+// const asks = _.map(orderbookResponse.asks.records, apiOrder => apiOrder.order);
+// const result = _.filter(asks, ask => orderUtils.isOpenOrder(ask));
+// return result;
+// }
diff --git a/packages/asset-buyer/src/forwarder_helper_impl.ts b/packages/asset-buyer/src/forwarder_helper_impl.ts
deleted file mode 100644
index a90edb0bb..000000000
--- a/packages/asset-buyer/src/forwarder_helper_impl.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { marketUtils } from '@0xproject/order-utils';
-import { SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
-
-import { constants } from './constants';
-import { ForwarderHelper, ForwarderHelperError, MarketBuyOrdersInfo, MarketBuyOrdersInfoRequest } from './types';
-import { forwarderHelperImplConfigUtils } from './utils/forwarder_helper_impl_config_utils';
-
-const SLIPPAGE_PERCENTAGE = new BigNumber(0.2); // 20% slippage protection, possibly move this into request interface
-
-export interface ForwarderHelperImplConfig {
- orders: SignedOrder[];
- feeOrders: SignedOrder[];
- remainingFillableMakerAssetAmounts?: BigNumber[];
- remainingFillableFeeAmounts?: BigNumber[];
-}
-
-export class ForwarderHelperImpl implements ForwarderHelper {
- public readonly config: ForwarderHelperImplConfig;
- constructor(config: ForwarderHelperImplConfig) {
- this.config = forwarderHelperImplConfigUtils.sortedConfig(config);
- }
- public getMarketBuyOrdersInfo(request: MarketBuyOrdersInfoRequest): MarketBuyOrdersInfo {
- const { makerAssetFillAmount, feePercentage } = request;
- const { orders, feeOrders, remainingFillableMakerAssetAmounts, remainingFillableFeeAmounts } = this.config;
- // TODO: make the slippage percentage customizable
- const slippageBufferAmount = makerAssetFillAmount.mul(SLIPPAGE_PERCENTAGE).round();
- const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
- orders,
- makerAssetFillAmount,
- {
- remainingFillableMakerAssetAmounts,
- slippageBufferAmount,
- },
- );
- if (remainingFillAmount.gt(constants.ZERO_AMOUNT)) {
- throw new Error(ForwarderHelperError.InsufficientMakerAssetLiquidity);
- }
- // TODO: 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
- const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
- resultOrders,
- feeOrders,
- {
- remainingFillableMakerAssetAmounts,
- remainingFillableFeeAmounts,
- },
- );
- if (remainingFeeAmount.gt(constants.ZERO_AMOUNT)) {
- throw new Error(ForwarderHelperError.InsufficientZrxLiquidity);
- }
- // TODO: calculate min and max eth usage
- // TODO: optimize orders call data
- return {
- makerAssetFillAmount,
- orders: resultOrders,
- feeOrders: resultFeeOrders,
- minEthAmount: constants.ZERO_AMOUNT,
- maxEthAmount: constants.ZERO_AMOUNT,
- feePercentage,
- };
- }
-}
diff --git a/packages/asset-buyer/src/index.ts b/packages/asset-buyer/src/index.ts
index eb3a34bd5..299b32edd 100644
--- a/packages/asset-buyer/src/index.ts
+++ b/packages/asset-buyer/src/index.ts
@@ -1,2 +1,2 @@
-export { forwarderHelperFactory } from './forwarder_helper_factory';
-export { ForwarderHelper, ForwarderHelperError, MarketBuyOrdersInfoRequest, MarketBuyOrdersInfo } from './types';
+export { AssetBuyerError, BuyQuote, BuyQuoteRequest } from './types';
+export { AssetBuyer } from './asset_buyers/asset_buyer';
diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts
index a7f02ff8d..8a12d0cf8 100644
--- a/packages/asset-buyer/src/types.ts
+++ b/packages/asset-buyer/src/types.ts
@@ -1,49 +1,42 @@
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
-export enum ForwarderHelperFactoryError {
- NoEtherTokenContractFound = 'NO_ETHER_TOKEN_CONTRACT_FOUND',
- NoZrxTokenContractFound = 'NO_ZRX_TOKEN_CONTRACT_FOUND',
- StandardRelayerApiError = 'STANDARD_RELAYER_API_ERROR',
-}
-
-export interface ForwarderHelper {
- /**
- * Given a MarketBuyOrdersInfoRequest, returns a MarketBuyOrdersInfo containing all information relevant to fulfilling the request
- * using the ForwarderContract marketBuyOrdersWithEth function.
- * @param request An object that conforms to MarketBuyOrdersInfoRequest. See type definition for more information.
- * @return An object that conforms to MarketBuyOrdersInfo that satisfies the request. See type definition for more information.
- */
- getMarketBuyOrdersInfo: (request: MarketBuyOrdersInfoRequest) => MarketBuyOrdersInfo;
-}
-
-export enum ForwarderHelperError {
- InsufficientMakerAssetLiquidity = 'INSUFFICIENT_MAKER_ASSET_LIQUIDITY',
- InsufficientZrxLiquidity = 'INSUFFICIENT_ZRX_LIQUIDITY',
-}
-
/**
- * makerAssetFillAmount: The amount of makerAsset requesting to be filled
- * feePercentage: Optional affiliate percentage amount factoring into eth amount calculations
+ * assetBuyAmount: The amount of asset to buy.
+ * feePercentage: Optional affiliate percentage amount factoring into eth amount calculations.
*/
-export interface MarketBuyOrdersInfoRequest {
- makerAssetFillAmount: BigNumber;
+export interface BuyQuoteRequest {
+ assetBuyAmount: BigNumber;
feePercentage?: BigNumber;
}
/**
- * makerAssetFillAmount: The amount of makerAsset requesting to be filled
- * orders: An array of objects conforming to SignedOrder. These orders can be used to cover the requested makerAssetFillAmount plus slippage
- * feeOrders: An array of objects conforming to SignedOrder. These orders can be used to cover the fees for the orders param above
- * minEthAmount: Amount of eth in wei to send with the tx for the most optimistic case
- * maxEthAmount: Amount of eth in wei to send with the tx for the worst case
- * feePercentage: Affiliate fee percentage used to calculate the eth amounts above. Passed thru directly from the request
+ * assetData: The asset information.
+ * 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.
+ * minRate: Min rate that needs to be paid in order to execute the buy.
+ * maxRate: Max rate that can be paid in order to execute the buy.
+ * assetBuyAmount: The amount of asset to buy. Passed through directly from the request.
+ * feePercentage: Affiliate fee percentage used to calculate the eth amounts above. Passed through directly from the request.
*/
-export interface MarketBuyOrdersInfo {
- makerAssetFillAmount: BigNumber;
+export interface BuyQuote {
+ assetData: string;
orders: SignedOrder[];
feeOrders: SignedOrder[];
- minEthAmount: BigNumber;
- maxEthAmount: BigNumber;
+ minRate: BigNumber;
+ maxRate: BigNumber;
+ assetBuyAmount: BigNumber;
feePercentage?: BigNumber;
}
+
+/**
+ * Possible errors 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',
+}
diff --git a/packages/asset-buyer/src/utils/forwarder_helper_impl_config_utils.ts b/packages/asset-buyer/src/utils/forwarder_helper_impl_config_utils.ts
index 253384f65..d3cbb651a 100644
--- a/packages/asset-buyer/src/utils/forwarder_helper_impl_config_utils.ts
+++ b/packages/asset-buyer/src/utils/forwarder_helper_impl_config_utils.ts
@@ -1,92 +1,92 @@
-import { sortingUtils } from '@0xproject/order-utils';
-import { SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
+// import { sortingUtils } from '@0xproject/order-utils';
+// import { SignedOrder } from '@0xproject/types';
+// import { BigNumber } from '@0xproject/utils';
+// import * as _ from 'lodash';
-import { ForwarderHelperImplConfig } from '../forwarder_helper_impl';
+// import { ForwarderHelperImplConfig } from '@0xproject/asset-buyer/src/asset_buyer';
-interface SignedOrderWithAmount extends SignedOrder {
- remainingFillAmount: BigNumber;
-}
+// interface SignedOrderWithAmount extends SignedOrder {
+// remainingFillAmount: BigNumber;
+// }
-export const forwarderHelperImplConfigUtils = {
- sortedConfig(config: ForwarderHelperImplConfig): ForwarderHelperImplConfig {
- const { orders, feeOrders, remainingFillableMakerAssetAmounts, remainingFillableFeeAmounts } = config;
- // TODO: provide a feeRate to the sorting function to more accurately sort based on the current market for ZRX tokens
- const orderSorter = (ordersToSort: SignedOrder[]) => {
- return sortingUtils.sortOrdersByFeeAdjustedRate(ordersToSort);
- };
- const sortOrdersResult = sortOrdersAndRemainingFillAmounts(
- orderSorter,
- orders,
- remainingFillableMakerAssetAmounts,
- );
- const feeOrderSorter = (ordersToSort: SignedOrder[]) => {
- return sortingUtils.sortFeeOrdersByFeeAdjustedRate(ordersToSort);
- };
- const sortFeeOrdersResult = sortOrdersAndRemainingFillAmounts(
- feeOrderSorter,
- feeOrders,
- remainingFillableFeeAmounts,
- );
- return {
- orders: sortOrdersResult.orders,
- feeOrders: sortFeeOrdersResult.orders,
- remainingFillableMakerAssetAmounts: sortOrdersResult.remainingFillAmounts,
- remainingFillableFeeAmounts: sortFeeOrdersResult.remainingFillAmounts,
- };
- },
-};
+// export const forwarderHelperImplConfigUtils = {
+// sortedConfig(config: ForwarderHelperImplConfig): ForwarderHelperImplConfig {
+// const { orders, feeOrders, remainingFillableMakerAssetAmounts, remainingFillableFeeAmounts } = config;
+// // TODO: provide a feeRate to the sorting function to more accurately sort based on the current market for ZRX tokens
+// const orderSorter = (ordersToSort: SignedOrder[]) => {
+// return sortingUtils.sortOrdersByFeeAdjustedRate(ordersToSort);
+// };
+// const sortOrdersResult = sortOrdersAndRemainingFillAmounts(
+// orderSorter,
+// orders,
+// remainingFillableMakerAssetAmounts,
+// );
+// const feeOrderSorter = (ordersToSort: SignedOrder[]) => {
+// return sortingUtils.sortFeeOrdersByFeeAdjustedRate(ordersToSort);
+// };
+// const sortFeeOrdersResult = sortOrdersAndRemainingFillAmounts(
+// feeOrderSorter,
+// feeOrders,
+// remainingFillableFeeAmounts,
+// );
+// return {
+// orders: sortOrdersResult.orders,
+// feeOrders: sortFeeOrdersResult.orders,
+// remainingFillableMakerAssetAmounts: sortOrdersResult.remainingFillAmounts,
+// remainingFillableFeeAmounts: sortFeeOrdersResult.remainingFillAmounts,
+// };
+// },
+// };
-type OrderSorter = (orders: SignedOrder[]) => SignedOrder[];
+// type OrderSorter = (orders: SignedOrder[]) => SignedOrder[];
-function sortOrdersAndRemainingFillAmounts(
- orderSorter: OrderSorter,
- orders: SignedOrder[],
- remainingFillAmounts?: BigNumber[],
-): { orders: SignedOrder[]; remainingFillAmounts?: BigNumber[] } {
- if (!_.isUndefined(remainingFillAmounts)) {
- // Bundle orders together with their remainingFillAmounts so that we can sort them together
- const orderWithAmounts = bundleSignedOrderWithAmounts(orders, remainingFillAmounts);
- // Sort
- const sortedOrderWithAmounts = orderSorter(orderWithAmounts) as SignedOrderWithAmount[];
- // Unbundle after sorting
- const unbundledSortedOrderWithAmounts = unbundleSignedOrderWithAmounts(sortedOrderWithAmounts);
- return {
- orders: unbundledSortedOrderWithAmounts.orders,
- remainingFillAmounts: unbundledSortedOrderWithAmounts.amounts,
- };
- } else {
- const sortedOrders = orderSorter(orders);
- return {
- orders: sortedOrders,
- };
- }
-}
+// function sortOrdersAndRemainingFillAmounts(
+// orderSorter: OrderSorter,
+// orders: SignedOrder[],
+// remainingFillAmounts?: BigNumber[],
+// ): { orders: SignedOrder[]; remainingFillAmounts?: BigNumber[] } {
+// if (!_.isUndefined(remainingFillAmounts)) {
+// // Bundle orders together with their remainingFillAmounts so that we can sort them together
+// const orderWithAmounts = bundleSignedOrderWithAmounts(orders, remainingFillAmounts);
+// // Sort
+// const sortedOrderWithAmounts = orderSorter(orderWithAmounts) as SignedOrderWithAmount[];
+// // Unbundle after sorting
+// const unbundledSortedOrderWithAmounts = unbundleSignedOrderWithAmounts(sortedOrderWithAmounts);
+// return {
+// orders: unbundledSortedOrderWithAmounts.orders,
+// remainingFillAmounts: unbundledSortedOrderWithAmounts.amounts,
+// };
+// } else {
+// const sortedOrders = orderSorter(orders);
+// return {
+// orders: sortedOrders,
+// };
+// }
+// }
-function bundleSignedOrderWithAmounts(orders: SignedOrder[], amounts: BigNumber[]): SignedOrderWithAmount[] {
- const ordersAndAmounts = _.map(orders, (order, index) => {
- return {
- ...order,
- remainingFillAmount: amounts[index],
- };
- });
- return ordersAndAmounts;
-}
+// function bundleSignedOrderWithAmounts(orders: SignedOrder[], amounts: BigNumber[]): SignedOrderWithAmount[] {
+// const ordersAndAmounts = _.map(orders, (order, index) => {
+// return {
+// ...order,
+// remainingFillAmount: amounts[index],
+// };
+// });
+// return ordersAndAmounts;
+// }
-function unbundleSignedOrderWithAmounts(
- signedOrderWithAmounts: SignedOrderWithAmount[],
-): { orders: SignedOrder[]; amounts: BigNumber[] } {
- const orders = _.map(signedOrderWithAmounts, order => {
- const { remainingFillAmount, ...rest } = order;
- return rest;
- });
- const amounts = _.map(signedOrderWithAmounts, order => {
- const { remainingFillAmount } = order;
- return remainingFillAmount;
- });
- return {
- orders,
- amounts,
- };
-}
+// function unbundleSignedOrderWithAmounts(
+// signedOrderWithAmounts: SignedOrderWithAmount[],
+// ): { orders: SignedOrder[]; amounts: BigNumber[] } {
+// const orders = _.map(signedOrderWithAmounts, order => {
+// const { remainingFillAmount, ...rest } = order;
+// return rest;
+// });
+// const amounts = _.map(signedOrderWithAmounts, order => {
+// const { remainingFillAmount } = order;
+// return remainingFillAmount;
+// });
+// return {
+// orders,
+// amounts,
+// };
+// }
diff --git a/packages/asset-buyer/test/forwarder_helper_impl_test.ts b/packages/asset-buyer/test/forwarder_helper_impl_test.ts
index 3c3b6db92..b7c014402 100644
--- a/packages/asset-buyer/test/forwarder_helper_impl_test.ts
+++ b/packages/asset-buyer/test/forwarder_helper_impl_test.ts
@@ -1,136 +1,136 @@
-import { testOrderFactory } from '@0xproject/order-utils/lib/test/utils/test_order_factory';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import 'mocha';
+// import { testOrderFactory } from '@0xproject/order-utils/lib/test/utils/test_order_factory';
+// import { BigNumber } from '@0xproject/utils';
+// import * as chai from 'chai';
+// import * as _ from 'lodash';
+// import 'mocha';
-import { ForwarderHelperImpl, ForwarderHelperImplConfig } from '../src/forwarder_helper_impl';
-import { ForwarderHelperError } from '../src/types';
+// import { ForwarderHelperImpl, ForwarderHelperImplConfig } from '@0xproject/asset-buyer/src/asset_buyer';
+// import { ForwarderHelperError } from '../src/types';
-import { chaiSetup } from './utils/chai_setup';
+// import { chaiSetup } from './utils/chai_setup';
-chaiSetup.configure();
-const expect = chai.expect;
+// chaiSetup.configure();
+// const expect = chai.expect;
-describe('ForwarderHelperImpl', () => {
- // rate: 2 takerAsset / makerAsset
- const testOrder1 = testOrderFactory.generateTestSignedOrder({
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(200),
- });
- // rate: 1 takerAsset / makerAsset
- const testOrder2 = testOrderFactory.generateTestSignedOrder({
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(100),
- });
- // rate: 3 takerAsset / makerAsset
- const testOrder3 = testOrderFactory.generateTestSignedOrder({
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(300),
- takerFee: new BigNumber(1),
- });
- // rate: 3 WETH / ZRX
- const testFeeOrder1 = testOrderFactory.generateTestSignedOrder({
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(300),
- });
- // rate: 2 WETH / ZRX
- const testFeeOrder2 = testOrderFactory.generateTestSignedOrder({
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(200),
- });
- // rate: 1 WETH / ZRX
- const testFeeOrder3 = testOrderFactory.generateTestSignedOrder({
- makerAssetAmount: new BigNumber(100),
- takerAssetAmount: new BigNumber(100),
- });
- const inputForwarderHelperConfig: ForwarderHelperImplConfig = {
- orders: [testOrder1, testOrder2, testOrder3],
- feeOrders: [testFeeOrder1, testFeeOrder2, testFeeOrder3],
- remainingFillableMakerAssetAmounts: [new BigNumber(1), new BigNumber(2), new BigNumber(3)],
- remainingFillableFeeAmounts: [new BigNumber(4), new BigNumber(5), new BigNumber(6)],
- };
- describe('#constructor', () => {
- const inputForwarderHelperConfigNoRemainingAmounts: ForwarderHelperImplConfig = {
- orders: [testOrder1, testOrder2, testOrder3],
- feeOrders: [testFeeOrder1, testFeeOrder2, testFeeOrder3],
- };
- it('sorts orders', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
- expect(forwarderHelper.config.orders).deep.equals([testOrder2, testOrder1, testOrder3]);
- });
- it('sorts fee orders', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
- expect(forwarderHelper.config.feeOrders).deep.equals([testFeeOrder3, testFeeOrder2, testFeeOrder1]);
- });
- it('sorts remainingFillableMakerAssetAmounts', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
- expect(forwarderHelper.config.remainingFillableMakerAssetAmounts).to.be.not.undefined();
- expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 0)).to.bignumber.equal(
- new BigNumber(2),
- );
- expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 1)).to.bignumber.equal(
- new BigNumber(1),
- );
- expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 2)).to.bignumber.equal(
- new BigNumber(3),
- );
- });
- it('sorts remainingFillableFeeAmounts', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
- expect(forwarderHelper.config.remainingFillableFeeAmounts).to.be.not.undefined();
- expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 0)).to.bignumber.equal(new BigNumber(6));
- expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 1)).to.bignumber.equal(new BigNumber(5));
- expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 2)).to.bignumber.equal(new BigNumber(4));
- });
- it('remainingFillableMakerAssetAmounts is undefined if none provided', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoRemainingAmounts);
- expect(forwarderHelper.config.remainingFillableMakerAssetAmounts).to.be.undefined();
- });
- it('remainingFillableFeeAmounts is undefined if none provided', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoRemainingAmounts);
- expect(forwarderHelper.config.remainingFillableFeeAmounts).to.be.undefined();
- });
- });
- describe('#getMarketBuyOrdersInfo', () => {
- it('throws if not enough makerAsset liquidity', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
- expect(() => {
- // request for 6 makerAsset units, because we have exactly 6 available we should throw because there is a built in slippage buffer
- forwarderHelper.getMarketBuyOrdersInfo({
- makerAssetFillAmount: new BigNumber(6),
- });
- }).to.throw(ForwarderHelperError.InsufficientMakerAssetLiquidity);
- });
- it('throws if not enough ZRX liquidity', () => {
- const inputForwarderHelperConfigNoFees: ForwarderHelperImplConfig = {
- orders: [testOrder1, testOrder2, testOrder3],
- feeOrders: [],
- };
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoFees);
- expect(() => {
- // request for 4 makerAsset units, we need fees but no fee orders exist, show we should throw
- forwarderHelper.getMarketBuyOrdersInfo({
- makerAssetFillAmount: new BigNumber(250),
- });
- }).to.throw(ForwarderHelperError.InsufficientZrxLiquidity);
- });
- it('passes the makerAssetFillAmount from the request to the info response', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
- const makerAssetFillAmount = new BigNumber(4);
- const info = forwarderHelper.getMarketBuyOrdersInfo({
- makerAssetFillAmount,
- });
- expect(info.makerAssetFillAmount).to.bignumber.equal(makerAssetFillAmount);
- });
- it('passes the feePercentage from the request to the info response', () => {
- const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
- const feePercentage = new BigNumber(0.2);
- const info = forwarderHelper.getMarketBuyOrdersInfo({
- makerAssetFillAmount: new BigNumber(4),
- feePercentage,
- });
- expect(info.feePercentage).to.bignumber.equal(feePercentage);
- });
- });
-});
+// describe('ForwarderHelperImpl', () => {
+// // rate: 2 takerAsset / makerAsset
+// const testOrder1 = testOrderFactory.generateTestSignedOrder({
+// makerAssetAmount: new BigNumber(100),
+// takerAssetAmount: new BigNumber(200),
+// });
+// // rate: 1 takerAsset / makerAsset
+// const testOrder2 = testOrderFactory.generateTestSignedOrder({
+// makerAssetAmount: new BigNumber(100),
+// takerAssetAmount: new BigNumber(100),
+// });
+// // rate: 3 takerAsset / makerAsset
+// const testOrder3 = testOrderFactory.generateTestSignedOrder({
+// makerAssetAmount: new BigNumber(100),
+// takerAssetAmount: new BigNumber(300),
+// takerFee: new BigNumber(1),
+// });
+// // rate: 3 WETH / ZRX
+// const testFeeOrder1 = testOrderFactory.generateTestSignedOrder({
+// makerAssetAmount: new BigNumber(100),
+// takerAssetAmount: new BigNumber(300),
+// });
+// // rate: 2 WETH / ZRX
+// const testFeeOrder2 = testOrderFactory.generateTestSignedOrder({
+// makerAssetAmount: new BigNumber(100),
+// takerAssetAmount: new BigNumber(200),
+// });
+// // rate: 1 WETH / ZRX
+// const testFeeOrder3 = testOrderFactory.generateTestSignedOrder({
+// makerAssetAmount: new BigNumber(100),
+// takerAssetAmount: new BigNumber(100),
+// });
+// const inputForwarderHelperConfig: ForwarderHelperImplConfig = {
+// orders: [testOrder1, testOrder2, testOrder3],
+// feeOrders: [testFeeOrder1, testFeeOrder2, testFeeOrder3],
+// remainingFillableMakerAssetAmounts: [new BigNumber(1), new BigNumber(2), new BigNumber(3)],
+// remainingFillableFeeAmounts: [new BigNumber(4), new BigNumber(5), new BigNumber(6)],
+// };
+// describe('#constructor', () => {
+// const inputForwarderHelperConfigNoRemainingAmounts: ForwarderHelperImplConfig = {
+// orders: [testOrder1, testOrder2, testOrder3],
+// feeOrders: [testFeeOrder1, testFeeOrder2, testFeeOrder3],
+// };
+// it('sorts orders', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
+// expect(forwarderHelper.config.orders).deep.equals([testOrder2, testOrder1, testOrder3]);
+// });
+// it('sorts fee orders', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
+// expect(forwarderHelper.config.feeOrders).deep.equals([testFeeOrder3, testFeeOrder2, testFeeOrder1]);
+// });
+// it('sorts remainingFillableMakerAssetAmounts', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
+// expect(forwarderHelper.config.remainingFillableMakerAssetAmounts).to.be.not.undefined();
+// expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 0)).to.bignumber.equal(
+// new BigNumber(2),
+// );
+// expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 1)).to.bignumber.equal(
+// new BigNumber(1),
+// );
+// expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 2)).to.bignumber.equal(
+// new BigNumber(3),
+// );
+// });
+// it('sorts remainingFillableFeeAmounts', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
+// expect(forwarderHelper.config.remainingFillableFeeAmounts).to.be.not.undefined();
+// expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 0)).to.bignumber.equal(new BigNumber(6));
+// expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 1)).to.bignumber.equal(new BigNumber(5));
+// expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 2)).to.bignumber.equal(new BigNumber(4));
+// });
+// it('remainingFillableMakerAssetAmounts is undefined if none provided', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoRemainingAmounts);
+// expect(forwarderHelper.config.remainingFillableMakerAssetAmounts).to.be.undefined();
+// });
+// it('remainingFillableFeeAmounts is undefined if none provided', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoRemainingAmounts);
+// expect(forwarderHelper.config.remainingFillableFeeAmounts).to.be.undefined();
+// });
+// });
+// describe('#getMarketBuyOrdersInfo', () => {
+// it('throws if not enough makerAsset liquidity', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
+// expect(() => {
+// // request for 6 makerAsset units, because we have exactly 6 available we should throw because there is a built in slippage buffer
+// forwarderHelper.getMarketBuyOrdersInfo({
+// makerAssetFillAmount: new BigNumber(6),
+// });
+// }).to.throw(ForwarderHelperError.InsufficientMakerAssetLiquidity);
+// });
+// it('throws if not enough ZRX liquidity', () => {
+// const inputForwarderHelperConfigNoFees: ForwarderHelperImplConfig = {
+// orders: [testOrder1, testOrder2, testOrder3],
+// feeOrders: [],
+// };
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoFees);
+// expect(() => {
+// // request for 4 makerAsset units, we need fees but no fee orders exist, show we should throw
+// forwarderHelper.getMarketBuyOrdersInfo({
+// makerAssetFillAmount: new BigNumber(250),
+// });
+// }).to.throw(ForwarderHelperError.InsufficientZrxLiquidity);
+// });
+// it('passes the makerAssetFillAmount from the request to the info response', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
+// const makerAssetFillAmount = new BigNumber(4);
+// const info = forwarderHelper.getMarketBuyOrdersInfo({
+// makerAssetFillAmount,
+// });
+// expect(info.makerAssetFillAmount).to.bignumber.equal(makerAssetFillAmount);
+// });
+// it('passes the feePercentage from the request to the info response', () => {
+// const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
+// const feePercentage = new BigNumber(0.2);
+// const info = forwarderHelper.getMarketBuyOrdersInfo({
+// makerAssetFillAmount: new BigNumber(4),
+// feePercentage,
+// });
+// expect(info.feePercentage).to.bignumber.equal(feePercentage);
+// });
+// });
+// });
diff --git a/tsconfig.json b/tsconfig.json
index a931b28b9..bc71dfb70 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -23,6 +23,7 @@
{ "path": "./packages/0x.js" },
{ "path": "./packages/abi-gen" },
{ "path": "./packages/assert" },
+ { "path": "./packages/asset-buyer" },
{ "path": "./packages/base-contract" },
{ "path": "./packages/connect" },
{ "path": "./packages/contract-wrappers" },
@@ -30,7 +31,6 @@
{ "path": "./packages/dev-utils" },
{ "path": "./packages/ethereum-types" },
{ "path": "./packages/fill-scenarios" },
- { "path": "./packages/forwarder-helper" },
{ "path": "./packages/json-schemas" },
{ "path": "./packages/metacoin" },
{ "path": "./packages/migrations" },