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 { chaiSetup } from './utils/chai_setup'; 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); }); }); });