Create initial AssetBuyer class
This commit is contained in:
		@@ -48,6 +48,8 @@
 | 
				
			|||||||
        "@0xproject/types": "^1.0.1",
 | 
					        "@0xproject/types": "^1.0.1",
 | 
				
			||||||
        "@0xproject/typescript-typings": "^2.0.0",
 | 
					        "@0xproject/typescript-typings": "^2.0.0",
 | 
				
			||||||
        "@0xproject/utils": "^1.0.8",
 | 
					        "@0xproject/utils": "^1.0.8",
 | 
				
			||||||
 | 
					        "@0xproject/web3-wrapper": "^2.0.2",
 | 
				
			||||||
 | 
					        "ethereum-types": "^1.0.6",
 | 
				
			||||||
        "lodash": "^4.17.10"
 | 
					        "lodash": "^4.17.10"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "devDependencies": {
 | 
					    "devDependencies": {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										129
									
								
								packages/asset-buyer/src/asset_buyers/asset_buyer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								packages/asset-buyer/src/asset_buyers/asset_buyer.ts
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,4 +3,5 @@ import { BigNumber } from '@0xproject/utils';
 | 
				
			|||||||
export const constants = {
 | 
					export const constants = {
 | 
				
			||||||
    ZERO_AMOUNT: new BigNumber(0),
 | 
					    ZERO_AMOUNT: new BigNumber(0),
 | 
				
			||||||
    NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
 | 
					    NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
 | 
				
			||||||
 | 
					    MAINNET_NETWORK_ID: 1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,261 +1,261 @@
 | 
				
			|||||||
import { assert } from '@0xproject/assert';
 | 
					// import { assert } from '@0xproject/assert';
 | 
				
			||||||
import { APIOrder, HttpClient, OrderbookResponse } from '@0xproject/connect';
 | 
					// import { APIOrder, HttpClient, OrderbookResponse } from '@0xproject/connect';
 | 
				
			||||||
import { ContractWrappers, OrderAndTraderInfo, OrderStatus } from '@0xproject/contract-wrappers';
 | 
					// import { ContractWrappers, OrderAndTraderInfo, OrderStatus } from '@0xproject/contract-wrappers';
 | 
				
			||||||
import { schemas } from '@0xproject/json-schemas';
 | 
					// import { schemas } from '@0xproject/json-schemas';
 | 
				
			||||||
import { assetDataUtils } from '@0xproject/order-utils';
 | 
					// import { assetDataUtils } from '@0xproject/order-utils';
 | 
				
			||||||
import { RemainingFillableCalculator } from '@0xproject/order-utils/lib/src/remaining_fillable_calculator';
 | 
					// import { RemainingFillableCalculator } from '@0xproject/order-utils/lib/src/remaining_fillable_calculator';
 | 
				
			||||||
import { RPCSubprovider, Web3ProviderEngine } from '@0xproject/subproviders';
 | 
					// import { RPCSubprovider, Web3ProviderEngine } from '@0xproject/subproviders';
 | 
				
			||||||
import { SignedOrder } from '@0xproject/types';
 | 
					// import { SignedOrder } from '@0xproject/types';
 | 
				
			||||||
import { BigNumber } from '@0xproject/utils';
 | 
					// import { BigNumber } from '@0xproject/utils';
 | 
				
			||||||
import * as _ from 'lodash';
 | 
					// import * as _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { constants } from './constants';
 | 
					// import { constants } from './constants';
 | 
				
			||||||
import { ForwarderHelperImpl, ForwarderHelperImplConfig } from './forwarder_helper_impl';
 | 
					// import { ForwarderHelperImpl, ForwarderHelperImplConfig } from '@0xproject/asset-buyer/src/asset_buyer';
 | 
				
			||||||
import { ForwarderHelper, ForwarderHelperFactoryError } from './types';
 | 
					// import { ForwarderHelper, ForwarderHelperFactoryError } from './types';
 | 
				
			||||||
import { orderUtils } from './utils/order_utils';
 | 
					// import { orderUtils } from './utils/order_utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const forwarderHelperFactory = {
 | 
					// export const forwarderHelperFactory = {
 | 
				
			||||||
    /**
 | 
					//     /**
 | 
				
			||||||
     * Given an array of orders and an array of feeOrders, get a ForwarderHelper
 | 
					//      * 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   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
 | 
					//      * @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
 | 
					//      * @return  A ForwarderHelper, see type for definition
 | 
				
			||||||
     */
 | 
					//      */
 | 
				
			||||||
    getForwarderHelperForOrders(orders: SignedOrder[], feeOrders: SignedOrder[] = []): ForwarderHelper {
 | 
					//     getForwarderHelperForOrders(orders: SignedOrder[], feeOrders: SignedOrder[] = []): ForwarderHelper {
 | 
				
			||||||
        assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
 | 
					//         assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
 | 
				
			||||||
        assert.doesConformToSchema('feeOrders', orders, schemas.signedOrdersSchema);
 | 
					//         assert.doesConformToSchema('feeOrders', orders, schemas.signedOrdersSchema);
 | 
				
			||||||
        // TODO: Add assertion here for orders all having the same makerAsset and takerAsset
 | 
					//         // TODO: Add assertion here for orders all having the same makerAsset and takerAsset
 | 
				
			||||||
        const config: ForwarderHelperImplConfig = {
 | 
					//         const config: ForwarderHelperImplConfig = {
 | 
				
			||||||
            orders,
 | 
					//             orders,
 | 
				
			||||||
            feeOrders,
 | 
					//             feeOrders,
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
        const helper = new ForwarderHelperImpl(config);
 | 
					//         const helper = new ForwarderHelperImpl(config);
 | 
				
			||||||
        return helper;
 | 
					//         return helper;
 | 
				
			||||||
    },
 | 
					//     },
 | 
				
			||||||
    /**
 | 
					//     /**
 | 
				
			||||||
     * Given a desired makerAsset and SRA url, get a ForwarderHelper
 | 
					//      * 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   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   sraUrl              A url pointing to an SRA v2 compliant endpoint.
 | 
				
			||||||
     * @param   rpcUrl              A url pointing to an ethereum node.
 | 
					//      * @param   rpcUrl              A url pointing to an ethereum node.
 | 
				
			||||||
     * @param   networkId           The ethereum networkId, defaults to 1 (mainnet).
 | 
					//      * @param   networkId           The ethereum networkId, defaults to 1 (mainnet).
 | 
				
			||||||
     * @return  A ForwarderHelper, see type for definition
 | 
					//      * @return  A ForwarderHelper, see type for definition
 | 
				
			||||||
     */
 | 
					//      */
 | 
				
			||||||
    async getForwarderHelperForMakerAssetDataAsync(
 | 
					//     async getForwarderHelperForMakerAssetDataAsync(
 | 
				
			||||||
        makerAssetData: string,
 | 
					//         makerAssetData: string,
 | 
				
			||||||
        sraUrl: string,
 | 
					//         sraUrl: string,
 | 
				
			||||||
        rpcUrl?: string,
 | 
					//         rpcUrl?: string,
 | 
				
			||||||
        networkId: number = 1,
 | 
					//         networkId: number = 1,
 | 
				
			||||||
    ): Promise<ForwarderHelper> {
 | 
					//     ): Promise<ForwarderHelper> {
 | 
				
			||||||
        assert.isHexString('makerAssetData', makerAssetData);
 | 
					//         assert.isHexString('makerAssetData', makerAssetData);
 | 
				
			||||||
        assert.isWebUri('sraUrl', sraUrl);
 | 
					//         assert.isWebUri('sraUrl', sraUrl);
 | 
				
			||||||
        if (!_.isUndefined(rpcUrl)) {
 | 
					//         if (!_.isUndefined(rpcUrl)) {
 | 
				
			||||||
            assert.isWebUri('rpcUrl', rpcUrl);
 | 
					//             assert.isWebUri('rpcUrl', rpcUrl);
 | 
				
			||||||
        }
 | 
					//         }
 | 
				
			||||||
        assert.isNumber('networkId', networkId);
 | 
					//         assert.isNumber('networkId', networkId);
 | 
				
			||||||
        // create provider
 | 
					//         // create provider
 | 
				
			||||||
        const providerEngine = new Web3ProviderEngine();
 | 
					//         const providerEngine = new Web3ProviderEngine();
 | 
				
			||||||
        if (!_.isUndefined(rpcUrl)) {
 | 
					//         if (!_.isUndefined(rpcUrl)) {
 | 
				
			||||||
            providerEngine.addProvider(new RPCSubprovider(rpcUrl));
 | 
					//             providerEngine.addProvider(new RPCSubprovider(rpcUrl));
 | 
				
			||||||
        }
 | 
					//         }
 | 
				
			||||||
        providerEngine.start();
 | 
					//         providerEngine.start();
 | 
				
			||||||
        // create contract wrappers given provider and networkId
 | 
					//         // create contract wrappers given provider and networkId
 | 
				
			||||||
        const contractWrappers = new ContractWrappers(providerEngine, { networkId });
 | 
					//         const contractWrappers = new ContractWrappers(providerEngine, { networkId });
 | 
				
			||||||
        // find ether token asset data
 | 
					//         // find ether token asset data
 | 
				
			||||||
        const etherTokenAddressIfExists = contractWrappers.etherToken.getContractAddressIfExists();
 | 
					//         const etherTokenAddressIfExists = contractWrappers.etherToken.getContractAddressIfExists();
 | 
				
			||||||
        if (_.isUndefined(etherTokenAddressIfExists)) {
 | 
					//         if (_.isUndefined(etherTokenAddressIfExists)) {
 | 
				
			||||||
            throw new Error(ForwarderHelperFactoryError.NoEtherTokenContractFound);
 | 
					//             throw new Error(ForwarderHelperFactoryError.NoEtherTokenContractFound);
 | 
				
			||||||
        }
 | 
					//         }
 | 
				
			||||||
        const etherTokenAssetData = assetDataUtils.encodeERC20AssetData(etherTokenAddressIfExists);
 | 
					//         const etherTokenAssetData = assetDataUtils.encodeERC20AssetData(etherTokenAddressIfExists);
 | 
				
			||||||
        // find zrx token asset data
 | 
					//         // find zrx token asset data
 | 
				
			||||||
        let zrxTokenAssetData: string;
 | 
					//         let zrxTokenAssetData: string;
 | 
				
			||||||
        try {
 | 
					//         try {
 | 
				
			||||||
            zrxTokenAssetData = contractWrappers.exchange.getZRXAssetData();
 | 
					//             zrxTokenAssetData = contractWrappers.exchange.getZRXAssetData();
 | 
				
			||||||
        } catch (err) {
 | 
					//         } catch (err) {
 | 
				
			||||||
            throw new Error(ForwarderHelperFactoryError.NoZrxTokenContractFound);
 | 
					//             throw new Error(ForwarderHelperFactoryError.NoZrxTokenContractFound);
 | 
				
			||||||
        }
 | 
					//         }
 | 
				
			||||||
        // get orderbooks for makerAsset/WETH and ZRX/WETH
 | 
					//         // get orderbooks for makerAsset/WETH and ZRX/WETH
 | 
				
			||||||
        const sraClient = new HttpClient(sraUrl);
 | 
					//         const sraClient = new HttpClient(sraUrl);
 | 
				
			||||||
        const orderbookRequests = [
 | 
					//         const orderbookRequests = [
 | 
				
			||||||
            { baseAssetData: makerAssetData, quoteAssetData: etherTokenAssetData },
 | 
					//             { baseAssetData: makerAssetData, quoteAssetData: etherTokenAssetData },
 | 
				
			||||||
            { baseAssetData: zrxTokenAssetData, quoteAssetData: etherTokenAssetData },
 | 
					//             { baseAssetData: zrxTokenAssetData, quoteAssetData: etherTokenAssetData },
 | 
				
			||||||
        ];
 | 
					//         ];
 | 
				
			||||||
        const requestOpts = { networkId };
 | 
					//         const requestOpts = { networkId };
 | 
				
			||||||
        let makerAssetOrderbook: OrderbookResponse;
 | 
					//         let makerAssetOrderbook: OrderbookResponse;
 | 
				
			||||||
        let zrxOrderbook: OrderbookResponse;
 | 
					//         let zrxOrderbook: OrderbookResponse;
 | 
				
			||||||
        try {
 | 
					//         try {
 | 
				
			||||||
            [makerAssetOrderbook, zrxOrderbook] = await Promise.all(
 | 
					//             [makerAssetOrderbook, zrxOrderbook] = await Promise.all(
 | 
				
			||||||
                _.map(orderbookRequests, request => sraClient.getOrderbookAsync(request, requestOpts)),
 | 
					//                 _.map(orderbookRequests, request => sraClient.getOrderbookAsync(request, requestOpts)),
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
        } catch (err) {
 | 
					//         } catch (err) {
 | 
				
			||||||
            throw new Error(ForwarderHelperFactoryError.StandardRelayerApiError);
 | 
					//             throw new Error(ForwarderHelperFactoryError.StandardRelayerApiError);
 | 
				
			||||||
        }
 | 
					//         }
 | 
				
			||||||
        // validate orders and find remaining fillable from on chain state or sra api
 | 
					//         // validate orders and find remaining fillable from on chain state or sra api
 | 
				
			||||||
        let ordersAndRemainingFillableMakerAssetAmounts: OrdersAndRemainingFillableMakerAssetAmounts;
 | 
					//         let ordersAndRemainingFillableMakerAssetAmounts: OrdersAndRemainingFillableMakerAssetAmounts;
 | 
				
			||||||
        let feeOrdersAndRemainingFillableMakerAssetAmounts: OrdersAndRemainingFillableMakerAssetAmounts;
 | 
					//         let feeOrdersAndRemainingFillableMakerAssetAmounts: OrdersAndRemainingFillableMakerAssetAmounts;
 | 
				
			||||||
        if (!_.isUndefined(rpcUrl)) {
 | 
					//         if (!_.isUndefined(rpcUrl)) {
 | 
				
			||||||
            // if we do have an rpc url, get on-chain orders and traders info via the OrderValidatorWrapper
 | 
					//             // if we do have an rpc url, get on-chain orders and traders info via the OrderValidatorWrapper
 | 
				
			||||||
            const ordersFromSra = getOpenAsksFromOrderbook(makerAssetOrderbook);
 | 
					//             const ordersFromSra = getOpenAsksFromOrderbook(makerAssetOrderbook);
 | 
				
			||||||
            const feeOrdersFromSra = getOpenAsksFromOrderbook(zrxOrderbook);
 | 
					//             const feeOrdersFromSra = getOpenAsksFromOrderbook(zrxOrderbook);
 | 
				
			||||||
            // TODO: try catch these requests and throw a more domain specific error
 | 
					//             // 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
 | 
					//             // 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(
 | 
					//             const [makerAssetOrdersAndTradersInfo, feeOrdersAndTradersInfo] = await Promise.all(
 | 
				
			||||||
                _.map([ordersFromSra, feeOrdersFromSra], ordersToBeValidated => {
 | 
					//                 _.map([ordersFromSra, feeOrdersFromSra], ordersToBeValidated => {
 | 
				
			||||||
                    const takerAddresses = _.map(ordersToBeValidated, () => constants.NULL_ADDRESS);
 | 
					//                     const takerAddresses = _.map(ordersToBeValidated, () => constants.NULL_ADDRESS);
 | 
				
			||||||
                    return contractWrappers.orderValidator.getOrdersAndTradersInfoAsync(
 | 
					//                     return contractWrappers.orderValidator.getOrdersAndTradersInfoAsync(
 | 
				
			||||||
                        ordersToBeValidated,
 | 
					//                         ordersToBeValidated,
 | 
				
			||||||
                        takerAddresses,
 | 
					//                         takerAddresses,
 | 
				
			||||||
                    );
 | 
					//                     );
 | 
				
			||||||
                }),
 | 
					//                 }),
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
            // take maker asset orders from SRA + on chain information and find the valid orders and remaining fillable maker asset amounts
 | 
					//             // take maker asset orders from SRA + on chain information and find the valid orders and remaining fillable maker asset amounts
 | 
				
			||||||
            ordersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
 | 
					//             ordersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
 | 
				
			||||||
                ordersFromSra,
 | 
					//                 ordersFromSra,
 | 
				
			||||||
                makerAssetOrdersAndTradersInfo,
 | 
					//                 makerAssetOrdersAndTradersInfo,
 | 
				
			||||||
                zrxTokenAssetData,
 | 
					//                 zrxTokenAssetData,
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
            // take fee orders from SRA + on chain information and find the valid orders and remaining fillable maker asset amounts
 | 
					//             // take fee orders from SRA + on chain information and find the valid orders and remaining fillable maker asset amounts
 | 
				
			||||||
            feeOrdersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
 | 
					//             feeOrdersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
 | 
				
			||||||
                feeOrdersFromSra,
 | 
					//                 feeOrdersFromSra,
 | 
				
			||||||
                feeOrdersAndTradersInfo,
 | 
					//                 feeOrdersAndTradersInfo,
 | 
				
			||||||
                zrxTokenAssetData,
 | 
					//                 zrxTokenAssetData,
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
        } else {
 | 
					//         } else {
 | 
				
			||||||
            // if we don't have an rpc url, assume all orders are valid and fallback to optional fill amounts from SRA
 | 
					//             // 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
 | 
					//             // if fill amounts are not available from the SRA, assume all orders are completely fillable
 | 
				
			||||||
            const apiOrdersFromSra = makerAssetOrderbook.asks.records;
 | 
					//             const apiOrdersFromSra = makerAssetOrderbook.asks.records;
 | 
				
			||||||
            const feeApiOrdersFromSra = zrxOrderbook.asks.records;
 | 
					//             const feeApiOrdersFromSra = zrxOrderbook.asks.records;
 | 
				
			||||||
            // take maker asset orders from SRA and the valid orders and remaining fillable maker asset amounts
 | 
					//             // take maker asset orders from SRA and the valid orders and remaining fillable maker asset amounts
 | 
				
			||||||
            ordersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
 | 
					//             ordersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
 | 
				
			||||||
                apiOrdersFromSra,
 | 
					//                 apiOrdersFromSra,
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
            // take fee orders from SRA and find the valid orders and remaining fillable maker asset amounts
 | 
					//             // take fee orders from SRA and find the valid orders and remaining fillable maker asset amounts
 | 
				
			||||||
            feeOrdersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
 | 
					//             feeOrdersAndRemainingFillableMakerAssetAmounts = getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
 | 
				
			||||||
                feeApiOrdersFromSra,
 | 
					//                 feeApiOrdersFromSra,
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
        }
 | 
					//         }
 | 
				
			||||||
        // compile final config
 | 
					//         // compile final config
 | 
				
			||||||
        const config: ForwarderHelperImplConfig = {
 | 
					//         const config: ForwarderHelperImplConfig = {
 | 
				
			||||||
            orders: ordersAndRemainingFillableMakerAssetAmounts.orders,
 | 
					//             orders: ordersAndRemainingFillableMakerAssetAmounts.orders,
 | 
				
			||||||
            feeOrders: feeOrdersAndRemainingFillableMakerAssetAmounts.orders,
 | 
					//             feeOrders: feeOrdersAndRemainingFillableMakerAssetAmounts.orders,
 | 
				
			||||||
            remainingFillableMakerAssetAmounts:
 | 
					//             remainingFillableMakerAssetAmounts:
 | 
				
			||||||
                ordersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
 | 
					//                 ordersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
 | 
				
			||||||
            remainingFillableFeeAmounts:
 | 
					//             remainingFillableFeeAmounts:
 | 
				
			||||||
                feeOrdersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
 | 
					//                 feeOrdersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
        const helper = new ForwarderHelperImpl(config);
 | 
					//         const helper = new ForwarderHelperImpl(config);
 | 
				
			||||||
        return helper;
 | 
					//         return helper;
 | 
				
			||||||
    },
 | 
					//     },
 | 
				
			||||||
};
 | 
					// };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface OrdersAndRemainingFillableMakerAssetAmounts {
 | 
					// interface OrdersAndRemainingFillableMakerAssetAmounts {
 | 
				
			||||||
    orders: SignedOrder[];
 | 
					//     orders: SignedOrder[];
 | 
				
			||||||
    remainingFillableMakerAssetAmounts: BigNumber[];
 | 
					//     remainingFillableMakerAssetAmounts: BigNumber[];
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					// /**
 | 
				
			||||||
 * Given an array of APIOrder objects from a standard relayer api, return an array
 | 
					//  * Given an array of APIOrder objects from a standard relayer api, return an array
 | 
				
			||||||
 * of fillable orders with their corresponding remainingFillableMakerAssetAmounts
 | 
					//  * of fillable orders with their corresponding remainingFillableMakerAssetAmounts
 | 
				
			||||||
 */
 | 
					//  */
 | 
				
			||||||
function getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
 | 
					// function getValidOrdersAndRemainingFillableMakerAssetAmountsFromApi(
 | 
				
			||||||
    apiOrders: APIOrder[],
 | 
					//     apiOrders: APIOrder[],
 | 
				
			||||||
): OrdersAndRemainingFillableMakerAssetAmounts {
 | 
					// ): OrdersAndRemainingFillableMakerAssetAmounts {
 | 
				
			||||||
    const result = _.reduce(
 | 
					//     const result = _.reduce(
 | 
				
			||||||
        apiOrders,
 | 
					//         apiOrders,
 | 
				
			||||||
        (acc, apiOrder) => {
 | 
					//         (acc, apiOrder) => {
 | 
				
			||||||
            // get current accumulations
 | 
					//             // get current accumulations
 | 
				
			||||||
            const { orders, remainingFillableMakerAssetAmounts } = acc;
 | 
					//             const { orders, remainingFillableMakerAssetAmounts } = acc;
 | 
				
			||||||
            // get order and metadata
 | 
					//             // get order and metadata
 | 
				
			||||||
            const { order, metaData } = apiOrder;
 | 
					//             const { order, metaData } = apiOrder;
 | 
				
			||||||
            // if the order is expired or not open, move on
 | 
					//             // if the order is expired or not open, move on
 | 
				
			||||||
            if (orderUtils.isOrderExpired(order) || !orderUtils.isOpenOrder(order)) {
 | 
					//             if (orderUtils.isOrderExpired(order) || !orderUtils.isOpenOrder(order)) {
 | 
				
			||||||
                return acc;
 | 
					//                 return acc;
 | 
				
			||||||
            }
 | 
					//             }
 | 
				
			||||||
            // calculate remainingFillableMakerAssetAmount from api metadata, else assume order is completely fillable
 | 
					//             // calculate remainingFillableMakerAssetAmount from api metadata, else assume order is completely fillable
 | 
				
			||||||
            const remainingFillableTakerAssetAmount = _.get(
 | 
					//             const remainingFillableTakerAssetAmount = _.get(
 | 
				
			||||||
                metaData,
 | 
					//                 metaData,
 | 
				
			||||||
                'remainingTakerAssetAmount',
 | 
					//                 'remainingTakerAssetAmount',
 | 
				
			||||||
                order.takerAssetAmount,
 | 
					//                 order.takerAssetAmount,
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
            const remainingFillableMakerAssetAmount = orderUtils.calculateRemainingMakerAssetAmount(
 | 
					//             const remainingFillableMakerAssetAmount = orderUtils.calculateRemainingMakerAssetAmount(
 | 
				
			||||||
                order,
 | 
					//                 order,
 | 
				
			||||||
                remainingFillableTakerAssetAmount,
 | 
					//                 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 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 there is not any maker asset left to fill, do not add
 | 
				
			||||||
            if (remainingFillableMakerAssetAmount.gt(constants.ZERO_AMOUNT)) {
 | 
					//             if (remainingFillableMakerAssetAmount.gt(constants.ZERO_AMOUNT)) {
 | 
				
			||||||
                return {
 | 
					//                 return {
 | 
				
			||||||
                    orders: _.concat(orders, order),
 | 
					//                     orders: _.concat(orders, order),
 | 
				
			||||||
                    remainingFillableMakerAssetAmounts: _.concat(
 | 
					//                     remainingFillableMakerAssetAmounts: _.concat(
 | 
				
			||||||
                        remainingFillableMakerAssetAmounts,
 | 
					//                         remainingFillableMakerAssetAmounts,
 | 
				
			||||||
                        remainingFillableMakerAssetAmount,
 | 
					//                         remainingFillableMakerAssetAmount,
 | 
				
			||||||
                    ),
 | 
					//                     ),
 | 
				
			||||||
                };
 | 
					//                 };
 | 
				
			||||||
            } else {
 | 
					//             } else {
 | 
				
			||||||
                return acc;
 | 
					//                 return acc;
 | 
				
			||||||
            }
 | 
					//             }
 | 
				
			||||||
        },
 | 
					//         },
 | 
				
			||||||
        { orders: [] as SignedOrder[], remainingFillableMakerAssetAmounts: [] as BigNumber[] },
 | 
					//         { orders: [] as SignedOrder[], remainingFillableMakerAssetAmounts: [] as BigNumber[] },
 | 
				
			||||||
    );
 | 
					//     );
 | 
				
			||||||
    return result;
 | 
					//     return result;
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					// /**
 | 
				
			||||||
 * Given an array of orders and corresponding on-chain infos, return a subset of the orders
 | 
					//  * 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
 | 
					//  * that are still fillable orders with their corresponding remainingFillableMakerAssetAmounts
 | 
				
			||||||
 */
 | 
					//  */
 | 
				
			||||||
function getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
 | 
					// function getValidOrdersAndRemainingFillableMakerAssetAmountsFromOnChain(
 | 
				
			||||||
    inputOrders: SignedOrder[],
 | 
					//     inputOrders: SignedOrder[],
 | 
				
			||||||
    ordersAndTradersInfo: OrderAndTraderInfo[],
 | 
					//     ordersAndTradersInfo: OrderAndTraderInfo[],
 | 
				
			||||||
    zrxAssetData: string,
 | 
					//     zrxAssetData: string,
 | 
				
			||||||
): OrdersAndRemainingFillableMakerAssetAmounts {
 | 
					// ): OrdersAndRemainingFillableMakerAssetAmounts {
 | 
				
			||||||
    // iterate through the input orders and find the ones that are still fillable
 | 
					//     // 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
 | 
					//     // for the orders that are still fillable, calculate the remaining fillable maker asset amount
 | 
				
			||||||
    const result = _.reduce(
 | 
					//     const result = _.reduce(
 | 
				
			||||||
        inputOrders,
 | 
					//         inputOrders,
 | 
				
			||||||
        (acc, order, index) => {
 | 
					//         (acc, order, index) => {
 | 
				
			||||||
            // get current accumulations
 | 
					//             // get current accumulations
 | 
				
			||||||
            const { orders, remainingFillableMakerAssetAmounts } = acc;
 | 
					//             const { orders, remainingFillableMakerAssetAmounts } = acc;
 | 
				
			||||||
            // get corresponding on-chain state for the order
 | 
					//             // get corresponding on-chain state for the order
 | 
				
			||||||
            const { orderInfo, traderInfo } = ordersAndTradersInfo[index];
 | 
					//             const { orderInfo, traderInfo } = ordersAndTradersInfo[index];
 | 
				
			||||||
            // if the order IS NOT fillable, do not add anything to the accumulations and continue iterating
 | 
					//             // if the order IS NOT fillable, do not add anything to the accumulations and continue iterating
 | 
				
			||||||
            if (orderInfo.orderStatus !== OrderStatus.FILLABLE) {
 | 
					//             if (orderInfo.orderStatus !== OrderStatus.FILLABLE) {
 | 
				
			||||||
                return acc;
 | 
					//                 return acc;
 | 
				
			||||||
            }
 | 
					//             }
 | 
				
			||||||
            // if the order IS fillable, add the order and calculate the remaining fillable amount
 | 
					//             // if the order IS fillable, add the order and calculate the remaining fillable amount
 | 
				
			||||||
            const transferrableAssetAmount = BigNumber.min([traderInfo.makerAllowance, traderInfo.makerBalance]);
 | 
					//             const transferrableAssetAmount = BigNumber.min([traderInfo.makerAllowance, traderInfo.makerBalance]);
 | 
				
			||||||
            const transferrableFeeAssetAmount = BigNumber.min([
 | 
					//             const transferrableFeeAssetAmount = BigNumber.min([
 | 
				
			||||||
                traderInfo.makerZrxAllowance,
 | 
					//                 traderInfo.makerZrxAllowance,
 | 
				
			||||||
                traderInfo.makerZrxBalance,
 | 
					//                 traderInfo.makerZrxBalance,
 | 
				
			||||||
            ]);
 | 
					//             ]);
 | 
				
			||||||
            const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
 | 
					//             const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
 | 
				
			||||||
            const remainingMakerAssetAmount = orderUtils.calculateRemainingMakerAssetAmount(
 | 
					//             const remainingMakerAssetAmount = orderUtils.calculateRemainingMakerAssetAmount(
 | 
				
			||||||
                order,
 | 
					//                 order,
 | 
				
			||||||
                remainingTakerAssetAmount,
 | 
					//                 remainingTakerAssetAmount,
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
            const remainingFillableCalculator = new RemainingFillableCalculator(
 | 
					//             const remainingFillableCalculator = new RemainingFillableCalculator(
 | 
				
			||||||
                order.makerFee,
 | 
					//                 order.makerFee,
 | 
				
			||||||
                order.makerAssetAmount,
 | 
					//                 order.makerAssetAmount,
 | 
				
			||||||
                order.makerAssetData === zrxAssetData,
 | 
					//                 order.makerAssetData === zrxAssetData,
 | 
				
			||||||
                transferrableAssetAmount,
 | 
					//                 transferrableAssetAmount,
 | 
				
			||||||
                transferrableFeeAssetAmount,
 | 
					//                 transferrableFeeAssetAmount,
 | 
				
			||||||
                remainingMakerAssetAmount,
 | 
					//                 remainingMakerAssetAmount,
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
            const remainingFillableAmount = remainingFillableCalculator.computeRemainingFillable();
 | 
					//             const remainingFillableAmount = remainingFillableCalculator.computeRemainingFillable();
 | 
				
			||||||
            return {
 | 
					//             return {
 | 
				
			||||||
                orders: _.concat(orders, order),
 | 
					//                 orders: _.concat(orders, order),
 | 
				
			||||||
                remainingFillableMakerAssetAmounts: _.concat(
 | 
					//                 remainingFillableMakerAssetAmounts: _.concat(
 | 
				
			||||||
                    remainingFillableMakerAssetAmounts,
 | 
					//                     remainingFillableMakerAssetAmounts,
 | 
				
			||||||
                    remainingFillableAmount,
 | 
					//                     remainingFillableAmount,
 | 
				
			||||||
                ),
 | 
					//                 ),
 | 
				
			||||||
            };
 | 
					//             };
 | 
				
			||||||
        },
 | 
					//         },
 | 
				
			||||||
        { orders: [] as SignedOrder[], remainingFillableMakerAssetAmounts: [] as BigNumber[] },
 | 
					//         { orders: [] as SignedOrder[], remainingFillableMakerAssetAmounts: [] as BigNumber[] },
 | 
				
			||||||
    );
 | 
					//     );
 | 
				
			||||||
    return result;
 | 
					//     return result;
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getOpenAsksFromOrderbook(orderbookResponse: OrderbookResponse): SignedOrder[] {
 | 
					// function getOpenAsksFromOrderbook(orderbookResponse: OrderbookResponse): SignedOrder[] {
 | 
				
			||||||
    const asks = _.map(orderbookResponse.asks.records, apiOrder => apiOrder.order);
 | 
					//     const asks = _.map(orderbookResponse.asks.records, apiOrder => apiOrder.order);
 | 
				
			||||||
    const result = _.filter(asks, ask => orderUtils.isOpenOrder(ask));
 | 
					//     const result = _.filter(asks, ask => orderUtils.isOpenOrder(ask));
 | 
				
			||||||
    return result;
 | 
					//     return result;
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,2 +1,2 @@
 | 
				
			|||||||
export { forwarderHelperFactory } from './forwarder_helper_factory';
 | 
					export { AssetBuyerError, BuyQuote, BuyQuoteRequest } from './types';
 | 
				
			||||||
export { ForwarderHelper, ForwarderHelperError, MarketBuyOrdersInfoRequest, MarketBuyOrdersInfo } from './types';
 | 
					export { AssetBuyer } from './asset_buyers/asset_buyer';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,49 +1,42 @@
 | 
				
			|||||||
import { SignedOrder } from '@0xproject/types';
 | 
					import { SignedOrder } from '@0xproject/types';
 | 
				
			||||||
import { BigNumber } from '@0xproject/utils';
 | 
					import { BigNumber } from '@0xproject/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export enum ForwarderHelperFactoryError {
 | 
					/**
 | 
				
			||||||
 | 
					 * assetBuyAmount: The amount of asset to buy.
 | 
				
			||||||
 | 
					 * feePercentage: Optional affiliate percentage amount factoring into eth amount calculations.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface BuyQuoteRequest {
 | 
				
			||||||
 | 
					    assetBuyAmount: BigNumber;
 | 
				
			||||||
 | 
					    feePercentage?: BigNumber;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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 BuyQuote {
 | 
				
			||||||
 | 
					    assetData: string;
 | 
				
			||||||
 | 
					    orders: SignedOrder[];
 | 
				
			||||||
 | 
					    feeOrders: SignedOrder[];
 | 
				
			||||||
 | 
					    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',
 | 
					    NoEtherTokenContractFound = 'NO_ETHER_TOKEN_CONTRACT_FOUND',
 | 
				
			||||||
    NoZrxTokenContractFound = 'NO_ZRX_TOKEN_CONTRACT_FOUND',
 | 
					    NoZrxTokenContractFound = 'NO_ZRX_TOKEN_CONTRACT_FOUND',
 | 
				
			||||||
    StandardRelayerApiError = 'STANDARD_RELAYER_API_ERROR',
 | 
					    StandardRelayerApiError = 'STANDARD_RELAYER_API_ERROR',
 | 
				
			||||||
}
 | 
					    InsufficientAssetLiquidity = 'INSUFFICIENT_ASSET_LIQUIDITY',
 | 
				
			||||||
 | 
					 | 
				
			||||||
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',
 | 
					    InsufficientZrxLiquidity = 'INSUFFICIENT_ZRX_LIQUIDITY',
 | 
				
			||||||
}
 | 
					    NoAddressAvailable = 'NO_ADDRESS_AVAILABLE',
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * makerAssetFillAmount: The amount of makerAsset requesting to be filled
 | 
					 | 
				
			||||||
 * feePercentage: Optional affiliate percentage amount factoring into eth amount calculations
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export interface MarketBuyOrdersInfoRequest {
 | 
					 | 
				
			||||||
    makerAssetFillAmount: 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
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export interface MarketBuyOrdersInfo {
 | 
					 | 
				
			||||||
    makerAssetFillAmount: BigNumber;
 | 
					 | 
				
			||||||
    orders: SignedOrder[];
 | 
					 | 
				
			||||||
    feeOrders: SignedOrder[];
 | 
					 | 
				
			||||||
    minEthAmount: BigNumber;
 | 
					 | 
				
			||||||
    maxEthAmount: BigNumber;
 | 
					 | 
				
			||||||
    feePercentage?: BigNumber;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,92 +1,92 @@
 | 
				
			|||||||
import { sortingUtils } from '@0xproject/order-utils';
 | 
					// import { sortingUtils } from '@0xproject/order-utils';
 | 
				
			||||||
import { SignedOrder } from '@0xproject/types';
 | 
					// import { SignedOrder } from '@0xproject/types';
 | 
				
			||||||
import { BigNumber } from '@0xproject/utils';
 | 
					// import { BigNumber } from '@0xproject/utils';
 | 
				
			||||||
import * as _ from 'lodash';
 | 
					// import * as _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { ForwarderHelperImplConfig } from '../forwarder_helper_impl';
 | 
					// import { ForwarderHelperImplConfig } from '@0xproject/asset-buyer/src/asset_buyer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface SignedOrderWithAmount extends SignedOrder {
 | 
					// interface SignedOrderWithAmount extends SignedOrder {
 | 
				
			||||||
    remainingFillAmount: BigNumber;
 | 
					//     remainingFillAmount: BigNumber;
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const forwarderHelperImplConfigUtils = {
 | 
					// export const forwarderHelperImplConfigUtils = {
 | 
				
			||||||
    sortedConfig(config: ForwarderHelperImplConfig): ForwarderHelperImplConfig {
 | 
					//     sortedConfig(config: ForwarderHelperImplConfig): ForwarderHelperImplConfig {
 | 
				
			||||||
        const { orders, feeOrders, remainingFillableMakerAssetAmounts, remainingFillableFeeAmounts } = config;
 | 
					//         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
 | 
					//         // TODO: provide a feeRate to the sorting function to more accurately sort based on the current market for ZRX tokens
 | 
				
			||||||
        const orderSorter = (ordersToSort: SignedOrder[]) => {
 | 
					//         const orderSorter = (ordersToSort: SignedOrder[]) => {
 | 
				
			||||||
            return sortingUtils.sortOrdersByFeeAdjustedRate(ordersToSort);
 | 
					//             return sortingUtils.sortOrdersByFeeAdjustedRate(ordersToSort);
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
        const sortOrdersResult = sortOrdersAndRemainingFillAmounts(
 | 
					//         const sortOrdersResult = sortOrdersAndRemainingFillAmounts(
 | 
				
			||||||
            orderSorter,
 | 
					//             orderSorter,
 | 
				
			||||||
            orders,
 | 
					//             orders,
 | 
				
			||||||
            remainingFillableMakerAssetAmounts,
 | 
					//             remainingFillableMakerAssetAmounts,
 | 
				
			||||||
        );
 | 
					//         );
 | 
				
			||||||
        const feeOrderSorter = (ordersToSort: SignedOrder[]) => {
 | 
					//         const feeOrderSorter = (ordersToSort: SignedOrder[]) => {
 | 
				
			||||||
            return sortingUtils.sortFeeOrdersByFeeAdjustedRate(ordersToSort);
 | 
					//             return sortingUtils.sortFeeOrdersByFeeAdjustedRate(ordersToSort);
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
        const sortFeeOrdersResult = sortOrdersAndRemainingFillAmounts(
 | 
					//         const sortFeeOrdersResult = sortOrdersAndRemainingFillAmounts(
 | 
				
			||||||
            feeOrderSorter,
 | 
					//             feeOrderSorter,
 | 
				
			||||||
            feeOrders,
 | 
					//             feeOrders,
 | 
				
			||||||
            remainingFillableFeeAmounts,
 | 
					//             remainingFillableFeeAmounts,
 | 
				
			||||||
        );
 | 
					//         );
 | 
				
			||||||
        return {
 | 
					//         return {
 | 
				
			||||||
            orders: sortOrdersResult.orders,
 | 
					//             orders: sortOrdersResult.orders,
 | 
				
			||||||
            feeOrders: sortFeeOrdersResult.orders,
 | 
					//             feeOrders: sortFeeOrdersResult.orders,
 | 
				
			||||||
            remainingFillableMakerAssetAmounts: sortOrdersResult.remainingFillAmounts,
 | 
					//             remainingFillableMakerAssetAmounts: sortOrdersResult.remainingFillAmounts,
 | 
				
			||||||
            remainingFillableFeeAmounts: sortFeeOrdersResult.remainingFillAmounts,
 | 
					//             remainingFillableFeeAmounts: sortFeeOrdersResult.remainingFillAmounts,
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
    },
 | 
					//     },
 | 
				
			||||||
};
 | 
					// };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type OrderSorter = (orders: SignedOrder[]) => SignedOrder[];
 | 
					// type OrderSorter = (orders: SignedOrder[]) => SignedOrder[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function sortOrdersAndRemainingFillAmounts(
 | 
					// function sortOrdersAndRemainingFillAmounts(
 | 
				
			||||||
    orderSorter: OrderSorter,
 | 
					//     orderSorter: OrderSorter,
 | 
				
			||||||
    orders: SignedOrder[],
 | 
					//     orders: SignedOrder[],
 | 
				
			||||||
    remainingFillAmounts?: BigNumber[],
 | 
					//     remainingFillAmounts?: BigNumber[],
 | 
				
			||||||
): { orders: SignedOrder[]; remainingFillAmounts?: BigNumber[] } {
 | 
					// ): { orders: SignedOrder[]; remainingFillAmounts?: BigNumber[] } {
 | 
				
			||||||
    if (!_.isUndefined(remainingFillAmounts)) {
 | 
					//     if (!_.isUndefined(remainingFillAmounts)) {
 | 
				
			||||||
        // Bundle orders together with their remainingFillAmounts so that we can sort them together
 | 
					//         // Bundle orders together with their remainingFillAmounts so that we can sort them together
 | 
				
			||||||
        const orderWithAmounts = bundleSignedOrderWithAmounts(orders, remainingFillAmounts);
 | 
					//         const orderWithAmounts = bundleSignedOrderWithAmounts(orders, remainingFillAmounts);
 | 
				
			||||||
        // Sort
 | 
					//         // Sort
 | 
				
			||||||
        const sortedOrderWithAmounts = orderSorter(orderWithAmounts) as SignedOrderWithAmount[];
 | 
					//         const sortedOrderWithAmounts = orderSorter(orderWithAmounts) as SignedOrderWithAmount[];
 | 
				
			||||||
        // Unbundle after sorting
 | 
					//         // Unbundle after sorting
 | 
				
			||||||
        const unbundledSortedOrderWithAmounts = unbundleSignedOrderWithAmounts(sortedOrderWithAmounts);
 | 
					//         const unbundledSortedOrderWithAmounts = unbundleSignedOrderWithAmounts(sortedOrderWithAmounts);
 | 
				
			||||||
        return {
 | 
					//         return {
 | 
				
			||||||
            orders: unbundledSortedOrderWithAmounts.orders,
 | 
					//             orders: unbundledSortedOrderWithAmounts.orders,
 | 
				
			||||||
            remainingFillAmounts: unbundledSortedOrderWithAmounts.amounts,
 | 
					//             remainingFillAmounts: unbundledSortedOrderWithAmounts.amounts,
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
    } else {
 | 
					//     } else {
 | 
				
			||||||
        const sortedOrders = orderSorter(orders);
 | 
					//         const sortedOrders = orderSorter(orders);
 | 
				
			||||||
        return {
 | 
					//         return {
 | 
				
			||||||
            orders: sortedOrders,
 | 
					//             orders: sortedOrders,
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
    }
 | 
					//     }
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function bundleSignedOrderWithAmounts(orders: SignedOrder[], amounts: BigNumber[]): SignedOrderWithAmount[] {
 | 
					// function bundleSignedOrderWithAmounts(orders: SignedOrder[], amounts: BigNumber[]): SignedOrderWithAmount[] {
 | 
				
			||||||
    const ordersAndAmounts = _.map(orders, (order, index) => {
 | 
					//     const ordersAndAmounts = _.map(orders, (order, index) => {
 | 
				
			||||||
        return {
 | 
					//         return {
 | 
				
			||||||
            ...order,
 | 
					//             ...order,
 | 
				
			||||||
            remainingFillAmount: amounts[index],
 | 
					//             remainingFillAmount: amounts[index],
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    return ordersAndAmounts;
 | 
					//     return ordersAndAmounts;
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function unbundleSignedOrderWithAmounts(
 | 
					// function unbundleSignedOrderWithAmounts(
 | 
				
			||||||
    signedOrderWithAmounts: SignedOrderWithAmount[],
 | 
					//     signedOrderWithAmounts: SignedOrderWithAmount[],
 | 
				
			||||||
): { orders: SignedOrder[]; amounts: BigNumber[] } {
 | 
					// ): { orders: SignedOrder[]; amounts: BigNumber[] } {
 | 
				
			||||||
    const orders = _.map(signedOrderWithAmounts, order => {
 | 
					//     const orders = _.map(signedOrderWithAmounts, order => {
 | 
				
			||||||
        const { remainingFillAmount, ...rest } = order;
 | 
					//         const { remainingFillAmount, ...rest } = order;
 | 
				
			||||||
        return rest;
 | 
					//         return rest;
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    const amounts = _.map(signedOrderWithAmounts, order => {
 | 
					//     const amounts = _.map(signedOrderWithAmounts, order => {
 | 
				
			||||||
        const { remainingFillAmount } = order;
 | 
					//         const { remainingFillAmount } = order;
 | 
				
			||||||
        return remainingFillAmount;
 | 
					//         return remainingFillAmount;
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    return {
 | 
					//     return {
 | 
				
			||||||
        orders,
 | 
					//         orders,
 | 
				
			||||||
        amounts,
 | 
					//         amounts,
 | 
				
			||||||
    };
 | 
					//     };
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,136 +1,136 @@
 | 
				
			|||||||
import { testOrderFactory } from '@0xproject/order-utils/lib/test/utils/test_order_factory';
 | 
					// import { testOrderFactory } from '@0xproject/order-utils/lib/test/utils/test_order_factory';
 | 
				
			||||||
import { BigNumber } from '@0xproject/utils';
 | 
					// import { BigNumber } from '@0xproject/utils';
 | 
				
			||||||
import * as chai from 'chai';
 | 
					// import * as chai from 'chai';
 | 
				
			||||||
import * as _ from 'lodash';
 | 
					// import * as _ from 'lodash';
 | 
				
			||||||
import 'mocha';
 | 
					// import 'mocha';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { ForwarderHelperImpl, ForwarderHelperImplConfig } from '../src/forwarder_helper_impl';
 | 
					// import { ForwarderHelperImpl, ForwarderHelperImplConfig } from '@0xproject/asset-buyer/src/asset_buyer';
 | 
				
			||||||
import { ForwarderHelperError } from '../src/types';
 | 
					// import { ForwarderHelperError } from '../src/types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { chaiSetup } from './utils/chai_setup';
 | 
					// import { chaiSetup } from './utils/chai_setup';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
chaiSetup.configure();
 | 
					// chaiSetup.configure();
 | 
				
			||||||
const expect = chai.expect;
 | 
					// const expect = chai.expect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('ForwarderHelperImpl', () => {
 | 
					// describe('ForwarderHelperImpl', () => {
 | 
				
			||||||
    // rate: 2 takerAsset / makerAsset
 | 
					//     // rate: 2 takerAsset / makerAsset
 | 
				
			||||||
    const testOrder1 = testOrderFactory.generateTestSignedOrder({
 | 
					//     const testOrder1 = testOrderFactory.generateTestSignedOrder({
 | 
				
			||||||
        makerAssetAmount: new BigNumber(100),
 | 
					//         makerAssetAmount: new BigNumber(100),
 | 
				
			||||||
        takerAssetAmount: new BigNumber(200),
 | 
					//         takerAssetAmount: new BigNumber(200),
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    // rate: 1 takerAsset / makerAsset
 | 
					//     // rate: 1 takerAsset / makerAsset
 | 
				
			||||||
    const testOrder2 = testOrderFactory.generateTestSignedOrder({
 | 
					//     const testOrder2 = testOrderFactory.generateTestSignedOrder({
 | 
				
			||||||
        makerAssetAmount: new BigNumber(100),
 | 
					//         makerAssetAmount: new BigNumber(100),
 | 
				
			||||||
        takerAssetAmount: new BigNumber(100),
 | 
					//         takerAssetAmount: new BigNumber(100),
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    // rate: 3 takerAsset / makerAsset
 | 
					//     // rate: 3 takerAsset / makerAsset
 | 
				
			||||||
    const testOrder3 = testOrderFactory.generateTestSignedOrder({
 | 
					//     const testOrder3 = testOrderFactory.generateTestSignedOrder({
 | 
				
			||||||
        makerAssetAmount: new BigNumber(100),
 | 
					//         makerAssetAmount: new BigNumber(100),
 | 
				
			||||||
        takerAssetAmount: new BigNumber(300),
 | 
					//         takerAssetAmount: new BigNumber(300),
 | 
				
			||||||
        takerFee: new BigNumber(1),
 | 
					//         takerFee: new BigNumber(1),
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    // rate: 3 WETH / ZRX
 | 
					//     // rate: 3 WETH / ZRX
 | 
				
			||||||
    const testFeeOrder1 = testOrderFactory.generateTestSignedOrder({
 | 
					//     const testFeeOrder1 = testOrderFactory.generateTestSignedOrder({
 | 
				
			||||||
        makerAssetAmount: new BigNumber(100),
 | 
					//         makerAssetAmount: new BigNumber(100),
 | 
				
			||||||
        takerAssetAmount: new BigNumber(300),
 | 
					//         takerAssetAmount: new BigNumber(300),
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    // rate: 2 WETH / ZRX
 | 
					//     // rate: 2 WETH / ZRX
 | 
				
			||||||
    const testFeeOrder2 = testOrderFactory.generateTestSignedOrder({
 | 
					//     const testFeeOrder2 = testOrderFactory.generateTestSignedOrder({
 | 
				
			||||||
        makerAssetAmount: new BigNumber(100),
 | 
					//         makerAssetAmount: new BigNumber(100),
 | 
				
			||||||
        takerAssetAmount: new BigNumber(200),
 | 
					//         takerAssetAmount: new BigNumber(200),
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    // rate: 1 WETH / ZRX
 | 
					//     // rate: 1 WETH / ZRX
 | 
				
			||||||
    const testFeeOrder3 = testOrderFactory.generateTestSignedOrder({
 | 
					//     const testFeeOrder3 = testOrderFactory.generateTestSignedOrder({
 | 
				
			||||||
        makerAssetAmount: new BigNumber(100),
 | 
					//         makerAssetAmount: new BigNumber(100),
 | 
				
			||||||
        takerAssetAmount: new BigNumber(100),
 | 
					//         takerAssetAmount: new BigNumber(100),
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    const inputForwarderHelperConfig: ForwarderHelperImplConfig = {
 | 
					//     const inputForwarderHelperConfig: ForwarderHelperImplConfig = {
 | 
				
			||||||
        orders: [testOrder1, testOrder2, testOrder3],
 | 
					//         orders: [testOrder1, testOrder2, testOrder3],
 | 
				
			||||||
        feeOrders: [testFeeOrder1, testFeeOrder2, testFeeOrder3],
 | 
					//         feeOrders: [testFeeOrder1, testFeeOrder2, testFeeOrder3],
 | 
				
			||||||
        remainingFillableMakerAssetAmounts: [new BigNumber(1), new BigNumber(2), new BigNumber(3)],
 | 
					//         remainingFillableMakerAssetAmounts: [new BigNumber(1), new BigNumber(2), new BigNumber(3)],
 | 
				
			||||||
        remainingFillableFeeAmounts: [new BigNumber(4), new BigNumber(5), new BigNumber(6)],
 | 
					//         remainingFillableFeeAmounts: [new BigNumber(4), new BigNumber(5), new BigNumber(6)],
 | 
				
			||||||
    };
 | 
					//     };
 | 
				
			||||||
    describe('#constructor', () => {
 | 
					//     describe('#constructor', () => {
 | 
				
			||||||
        const inputForwarderHelperConfigNoRemainingAmounts: ForwarderHelperImplConfig = {
 | 
					//         const inputForwarderHelperConfigNoRemainingAmounts: ForwarderHelperImplConfig = {
 | 
				
			||||||
            orders: [testOrder1, testOrder2, testOrder3],
 | 
					//             orders: [testOrder1, testOrder2, testOrder3],
 | 
				
			||||||
            feeOrders: [testFeeOrder1, testFeeOrder2, testFeeOrder3],
 | 
					//             feeOrders: [testFeeOrder1, testFeeOrder2, testFeeOrder3],
 | 
				
			||||||
        };
 | 
					//         };
 | 
				
			||||||
        it('sorts orders', () => {
 | 
					//         it('sorts orders', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
				
			||||||
            expect(forwarderHelper.config.orders).deep.equals([testOrder2, testOrder1, testOrder3]);
 | 
					//             expect(forwarderHelper.config.orders).deep.equals([testOrder2, testOrder1, testOrder3]);
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
        it('sorts fee orders', () => {
 | 
					//         it('sorts fee orders', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
				
			||||||
            expect(forwarderHelper.config.feeOrders).deep.equals([testFeeOrder3, testFeeOrder2, testFeeOrder1]);
 | 
					//             expect(forwarderHelper.config.feeOrders).deep.equals([testFeeOrder3, testFeeOrder2, testFeeOrder1]);
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
        it('sorts remainingFillableMakerAssetAmounts', () => {
 | 
					//         it('sorts remainingFillableMakerAssetAmounts', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
				
			||||||
            expect(forwarderHelper.config.remainingFillableMakerAssetAmounts).to.be.not.undefined();
 | 
					//             expect(forwarderHelper.config.remainingFillableMakerAssetAmounts).to.be.not.undefined();
 | 
				
			||||||
            expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 0)).to.bignumber.equal(
 | 
					//             expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 0)).to.bignumber.equal(
 | 
				
			||||||
                new BigNumber(2),
 | 
					//                 new BigNumber(2),
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
            expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 1)).to.bignumber.equal(
 | 
					//             expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 1)).to.bignumber.equal(
 | 
				
			||||||
                new BigNumber(1),
 | 
					//                 new BigNumber(1),
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
            expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 2)).to.bignumber.equal(
 | 
					//             expect(_.nth(forwarderHelper.config.remainingFillableMakerAssetAmounts, 2)).to.bignumber.equal(
 | 
				
			||||||
                new BigNumber(3),
 | 
					//                 new BigNumber(3),
 | 
				
			||||||
            );
 | 
					//             );
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
        it('sorts remainingFillableFeeAmounts', () => {
 | 
					//         it('sorts remainingFillableFeeAmounts', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
				
			||||||
            expect(forwarderHelper.config.remainingFillableFeeAmounts).to.be.not.undefined();
 | 
					//             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, 0)).to.bignumber.equal(new BigNumber(6));
 | 
				
			||||||
            expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 1)).to.bignumber.equal(new BigNumber(5));
 | 
					//             expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 1)).to.bignumber.equal(new BigNumber(5));
 | 
				
			||||||
            expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 2)).to.bignumber.equal(new BigNumber(4));
 | 
					//             expect(_.nth(forwarderHelper.config.remainingFillableFeeAmounts, 2)).to.bignumber.equal(new BigNumber(4));
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
        it('remainingFillableMakerAssetAmounts is undefined if none provided', () => {
 | 
					//         it('remainingFillableMakerAssetAmounts is undefined if none provided', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoRemainingAmounts);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoRemainingAmounts);
 | 
				
			||||||
            expect(forwarderHelper.config.remainingFillableMakerAssetAmounts).to.be.undefined();
 | 
					//             expect(forwarderHelper.config.remainingFillableMakerAssetAmounts).to.be.undefined();
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
        it('remainingFillableFeeAmounts is undefined if none provided', () => {
 | 
					//         it('remainingFillableFeeAmounts is undefined if none provided', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoRemainingAmounts);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoRemainingAmounts);
 | 
				
			||||||
            expect(forwarderHelper.config.remainingFillableFeeAmounts).to.be.undefined();
 | 
					//             expect(forwarderHelper.config.remainingFillableFeeAmounts).to.be.undefined();
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
    describe('#getMarketBuyOrdersInfo', () => {
 | 
					//     describe('#getMarketBuyOrdersInfo', () => {
 | 
				
			||||||
        it('throws if not enough makerAsset liquidity', () => {
 | 
					//         it('throws if not enough makerAsset liquidity', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
				
			||||||
            expect(() => {
 | 
					//             expect(() => {
 | 
				
			||||||
                // request for 6 makerAsset units, because we have exactly 6 available we should throw because there is a built in slippage buffer
 | 
					//                 // request for 6 makerAsset units, because we have exactly 6 available we should throw because there is a built in slippage buffer
 | 
				
			||||||
                forwarderHelper.getMarketBuyOrdersInfo({
 | 
					//                 forwarderHelper.getMarketBuyOrdersInfo({
 | 
				
			||||||
                    makerAssetFillAmount: new BigNumber(6),
 | 
					//                     makerAssetFillAmount: new BigNumber(6),
 | 
				
			||||||
                });
 | 
					//                 });
 | 
				
			||||||
            }).to.throw(ForwarderHelperError.InsufficientMakerAssetLiquidity);
 | 
					//             }).to.throw(ForwarderHelperError.InsufficientMakerAssetLiquidity);
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
        it('throws if not enough ZRX liquidity', () => {
 | 
					//         it('throws if not enough ZRX liquidity', () => {
 | 
				
			||||||
            const inputForwarderHelperConfigNoFees: ForwarderHelperImplConfig = {
 | 
					//             const inputForwarderHelperConfigNoFees: ForwarderHelperImplConfig = {
 | 
				
			||||||
                orders: [testOrder1, testOrder2, testOrder3],
 | 
					//                 orders: [testOrder1, testOrder2, testOrder3],
 | 
				
			||||||
                feeOrders: [],
 | 
					//                 feeOrders: [],
 | 
				
			||||||
            };
 | 
					//             };
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoFees);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfigNoFees);
 | 
				
			||||||
            expect(() => {
 | 
					//             expect(() => {
 | 
				
			||||||
                // request for 4 makerAsset units, we need fees but no fee orders exist, show we should throw
 | 
					//                 // request for 4 makerAsset units, we need fees but no fee orders exist, show we should throw
 | 
				
			||||||
                forwarderHelper.getMarketBuyOrdersInfo({
 | 
					//                 forwarderHelper.getMarketBuyOrdersInfo({
 | 
				
			||||||
                    makerAssetFillAmount: new BigNumber(250),
 | 
					//                     makerAssetFillAmount: new BigNumber(250),
 | 
				
			||||||
                });
 | 
					//                 });
 | 
				
			||||||
            }).to.throw(ForwarderHelperError.InsufficientZrxLiquidity);
 | 
					//             }).to.throw(ForwarderHelperError.InsufficientZrxLiquidity);
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
        it('passes the makerAssetFillAmount from the request to the info response', () => {
 | 
					//         it('passes the makerAssetFillAmount from the request to the info response', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
				
			||||||
            const makerAssetFillAmount = new BigNumber(4);
 | 
					//             const makerAssetFillAmount = new BigNumber(4);
 | 
				
			||||||
            const info = forwarderHelper.getMarketBuyOrdersInfo({
 | 
					//             const info = forwarderHelper.getMarketBuyOrdersInfo({
 | 
				
			||||||
                makerAssetFillAmount,
 | 
					//                 makerAssetFillAmount,
 | 
				
			||||||
            });
 | 
					//             });
 | 
				
			||||||
            expect(info.makerAssetFillAmount).to.bignumber.equal(makerAssetFillAmount);
 | 
					//             expect(info.makerAssetFillAmount).to.bignumber.equal(makerAssetFillAmount);
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
        it('passes the feePercentage from the request to the info response', () => {
 | 
					//         it('passes the feePercentage from the request to the info response', () => {
 | 
				
			||||||
            const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
					//             const forwarderHelper = new ForwarderHelperImpl(inputForwarderHelperConfig);
 | 
				
			||||||
            const feePercentage = new BigNumber(0.2);
 | 
					//             const feePercentage = new BigNumber(0.2);
 | 
				
			||||||
            const info = forwarderHelper.getMarketBuyOrdersInfo({
 | 
					//             const info = forwarderHelper.getMarketBuyOrdersInfo({
 | 
				
			||||||
                makerAssetFillAmount: new BigNumber(4),
 | 
					//                 makerAssetFillAmount: new BigNumber(4),
 | 
				
			||||||
                feePercentage,
 | 
					//                 feePercentage,
 | 
				
			||||||
            });
 | 
					//             });
 | 
				
			||||||
            expect(info.feePercentage).to.bignumber.equal(feePercentage);
 | 
					//             expect(info.feePercentage).to.bignumber.equal(feePercentage);
 | 
				
			||||||
        });
 | 
					//         });
 | 
				
			||||||
    });
 | 
					//     });
 | 
				
			||||||
});
 | 
					// });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@
 | 
				
			|||||||
        { "path": "./packages/0x.js" },
 | 
					        { "path": "./packages/0x.js" },
 | 
				
			||||||
        { "path": "./packages/abi-gen" },
 | 
					        { "path": "./packages/abi-gen" },
 | 
				
			||||||
        { "path": "./packages/assert" },
 | 
					        { "path": "./packages/assert" },
 | 
				
			||||||
 | 
					        { "path": "./packages/asset-buyer" },
 | 
				
			||||||
        { "path": "./packages/base-contract" },
 | 
					        { "path": "./packages/base-contract" },
 | 
				
			||||||
        { "path": "./packages/connect" },
 | 
					        { "path": "./packages/connect" },
 | 
				
			||||||
        { "path": "./packages/contract-wrappers" },
 | 
					        { "path": "./packages/contract-wrappers" },
 | 
				
			||||||
@@ -30,7 +31,6 @@
 | 
				
			|||||||
        { "path": "./packages/dev-utils" },
 | 
					        { "path": "./packages/dev-utils" },
 | 
				
			||||||
        { "path": "./packages/ethereum-types" },
 | 
					        { "path": "./packages/ethereum-types" },
 | 
				
			||||||
        { "path": "./packages/fill-scenarios" },
 | 
					        { "path": "./packages/fill-scenarios" },
 | 
				
			||||||
        { "path": "./packages/forwarder-helper" },
 | 
					 | 
				
			||||||
        { "path": "./packages/json-schemas" },
 | 
					        { "path": "./packages/json-schemas" },
 | 
				
			||||||
        { "path": "./packages/metacoin" },
 | 
					        { "path": "./packages/metacoin" },
 | 
				
			||||||
        { "path": "./packages/migrations" },
 | 
					        { "path": "./packages/migrations" },
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user