aboutsummaryrefslogtreecommitdiffstats
path: root/packages/order-utils/test
diff options
context:
space:
mode:
Diffstat (limited to 'packages/order-utils/test')
-rw-r--r--packages/order-utils/test/market_utils_test.ts50
-rw-r--r--packages/order-utils/test/order_state_utils_test.ts124
-rw-r--r--packages/order-utils/test/rate_utils_test.ts55
-rw-r--r--packages/order-utils/test/sorting_utils_test.ts67
4 files changed, 264 insertions, 32 deletions
diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts
index 5d94cc55c..cce97e0e4 100644
--- a/packages/order-utils/test/market_utils_test.ts
+++ b/packages/order-utils/test/market_utils_test.ts
@@ -19,7 +19,6 @@ describe('marketUtils', () => {
const fillAmount = new BigNumber(10);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
[],
- [],
fillAmount,
);
expect(resultOrders).to.be.empty;
@@ -35,8 +34,6 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
- const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => {
// try to fill 20 units of makerAsset
// include 10 units of slippageBufferAmount
@@ -44,9 +41,10 @@ describe('marketUtils', () => {
const slippageBufferAmount = new BigNumber(10);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
- slippageBufferAmount,
+ {
+ slippageBufferAmount,
+ },
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -58,9 +56,10 @@ describe('marketUtils', () => {
const slippageBufferAmount = new BigNumber(10);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
- slippageBufferAmount,
+ {
+ slippageBufferAmount,
+ },
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -72,9 +71,10 @@ describe('marketUtils', () => {
const slippageBufferAmount = new BigNumber(5);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
- slippageBufferAmount,
+ {
+ slippageBufferAmount,
+ },
);
expect(resultOrders).to.be.deep.equal(inputOrders);
expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5));
@@ -84,7 +84,6 @@ describe('marketUtils', () => {
const fillAmount = new BigNumber(10);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
@@ -95,7 +94,6 @@ describe('marketUtils', () => {
const fillAmount = new BigNumber(15);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
);
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
@@ -121,8 +119,10 @@ describe('marketUtils', () => {
const fillAmount = new BigNumber(30);
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
inputOrders,
- remainingFillableMakerAssetAmounts,
fillAmount,
+ {
+ remainingFillableMakerAssetAmounts,
+ },
);
expect(resultOrders).to.be.deep.equal([inputOrders[1], inputOrders[2]]);
expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(15));
@@ -138,15 +138,11 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableFeeAmounts that equal the zrxAmount
- const remainingFillableFeeAmounts = [zrxAmount, zrxAmount, zrxAmount];
describe('no target orders', () => {
it('returns empty and zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
[],
- [],
inputFeeOrders,
- remainingFillableFeeAmounts,
);
expect(resultOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -169,9 +165,10 @@ describe('marketUtils', () => {
it('returns empty and non-zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
- [],
[],
+ {
+ remainingFillableMakerAssetAmounts,
+ },
);
expect(resultOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
@@ -186,14 +183,10 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
- const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns empty and zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
inputFeeOrders,
- remainingFillableFeeAmounts,
);
expect(resultOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -211,14 +204,10 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
- const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns input fee orders and zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
inputFeeOrders,
- remainingFillableFeeAmounts,
);
expect(resultOrders).to.be.deep.equal(inputFeeOrders);
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -244,9 +233,10 @@ describe('marketUtils', () => {
it('returns first two input fee orders and zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
inputFeeOrders,
- remainingFillableFeeAmounts,
+ {
+ remainingFillableMakerAssetAmounts,
+ },
);
expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]);
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
@@ -264,14 +254,10 @@ describe('marketUtils', () => {
},
3,
);
- // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
- const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns input fee orders and non-zero remainingFeeAmount', async () => {
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
- remainingFillableMakerAssetAmounts,
inputFeeOrders,
- remainingFillableFeeAmounts,
);
expect(resultOrders).to.be.deep.equal(inputFeeOrders);
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
diff --git a/packages/order-utils/test/order_state_utils_test.ts b/packages/order-utils/test/order_state_utils_test.ts
new file mode 100644
index 000000000..91ef23b69
--- /dev/null
+++ b/packages/order-utils/test/order_state_utils_test.ts
@@ -0,0 +1,124 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { AbstractBalanceAndProxyAllowanceFetcher } from '../src/abstract/abstract_balance_and_proxy_allowance_fetcher';
+import { AbstractOrderFilledCancelledFetcher } from '../src/abstract/abstract_order_filled_cancelled_fetcher';
+import { OrderStateUtils } from '../src/order_state_utils';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrderFactory } from './utils/test_order_factory';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('OrderStateUtils', () => {
+ describe('#getOpenOrderStateAsync', () => {
+ const buildMockBalanceFetcher = (takerBalance: BigNumber): AbstractBalanceAndProxyAllowanceFetcher => {
+ const balanceFetcher = {
+ async getBalanceAsync(_assetData: string, _userAddress: string): Promise<BigNumber> {
+ return takerBalance;
+ },
+ async getProxyAllowanceAsync(_assetData: string, _userAddress: string): Promise<BigNumber> {
+ return takerBalance;
+ },
+ };
+ return balanceFetcher;
+ };
+ const buildMockOrderFilledFetcher = (
+ filledAmount: BigNumber = new BigNumber(0),
+ cancelled: boolean = false,
+ ): AbstractOrderFilledCancelledFetcher => {
+ const orderFetcher = {
+ async getFilledTakerAmountAsync(_orderHash: string): Promise<BigNumber> {
+ return filledAmount;
+ },
+ async isOrderCancelledAsync(_orderHash: string): Promise<boolean> {
+ return cancelled;
+ },
+ getZRXAssetData(): string {
+ return '';
+ },
+ };
+ return orderFetcher;
+ };
+ it('should have valid order state if order can be fully filled with small maker amount', async () => {
+ const makerAssetAmount = new BigNumber(10);
+ const takerAssetAmount = new BigNumber(10000000000000000);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = new BigNumber(0);
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
+ expect(orderState.isValid).to.eq(true);
+ });
+ it('should be invalid when an order is partially filled where only a rounding error remains', async () => {
+ const makerAssetAmount = new BigNumber(1001);
+ const takerAssetAmount = new BigNumber(3);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = new BigNumber(2);
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
+ expect(orderState.isValid).to.eq(false);
+ });
+ it('should be invalid when an order is cancelled', async () => {
+ const makerAssetAmount = new BigNumber(1000);
+ const takerAssetAmount = new BigNumber(2);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = new BigNumber(0);
+ const isCancelled = true;
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
+ expect(orderState.isValid).to.eq(false);
+ });
+ it('should be invalid when an order is fully filled', async () => {
+ const makerAssetAmount = new BigNumber(1000);
+ const takerAssetAmount = new BigNumber(2);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = takerAssetAmount;
+ const isCancelled = false;
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
+ expect(orderState.isValid).to.eq(false);
+ });
+ });
+});
diff --git a/packages/order-utils/test/rate_utils_test.ts b/packages/order-utils/test/rate_utils_test.ts
new file mode 100644
index 000000000..2e299c209
--- /dev/null
+++ b/packages/order-utils/test/rate_utils_test.ts
@@ -0,0 +1,55 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { rateUtils } from '../src';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrderFactory } from './utils/test_order_factory';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('rateUtils', () => {
+ const testOrder = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(100),
+ takerFee: new BigNumber(20),
+ });
+ describe('#getFeeAdjustedRateOfOrder', () => {
+ it('throws when feeRate is less than zero', async () => {
+ const feeRate = new BigNumber(-1);
+ expect(() => rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate)).to.throw(
+ 'Expected feeRate: -1 to be greater than or equal to 0',
+ );
+ });
+ it('correctly calculates fee adjusted rate when feeRate is provided', async () => {
+ const feeRate = new BigNumber(2); // ZRX costs 2 units of takerAsset per 1 unit of ZRX
+ const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate);
+ // the order actually takes 100 + (2 * 20) takerAsset units to fill 100 units of makerAsset
+ expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1.4));
+ });
+ it('correctly calculates fee adjusted rate when no feeRate is provided', async () => {
+ const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfOrder(testOrder);
+ // because no feeRate was provided we just assume 0 fees
+ // the order actually takes 100 takerAsset units to fill 100 units of makerAsset
+ expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1));
+ });
+ });
+ describe('#getFeeAdjustedRateOfFeeOrder', () => {
+ it('throws when takerFee exceeds makerAssetAmount', async () => {
+ const badOrder = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerFee: new BigNumber(101),
+ });
+ expect(() => rateUtils.getFeeAdjustedRateOfFeeOrder(badOrder)).to.throw(
+ 'Expected takerFee: "101" to be less than makerAssetAmount: "100"',
+ );
+ });
+ it('correctly calculates fee adjusted rate', async () => {
+ const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfFeeOrder(testOrder);
+ // the order actually takes 100 takerAsset units to fill (100 - 20) units of makerAsset
+ expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1.25));
+ });
+ });
+});
diff --git a/packages/order-utils/test/sorting_utils_test.ts b/packages/order-utils/test/sorting_utils_test.ts
new file mode 100644
index 000000000..016432505
--- /dev/null
+++ b/packages/order-utils/test/sorting_utils_test.ts
@@ -0,0 +1,67 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { sortingUtils } from '../src';
+
+import { chaiSetup } from './utils/chai_setup';
+import { testOrderFactory } from './utils/test_order_factory';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('sortingUtils', () => {
+ describe('#sortOrdersByFeeAdjustedRate', () => {
+ const feeRate = new BigNumber(1); // ZRX costs 1 unit of takerAsset per 1 unit of ZRX
+ // 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: 2.5 takerAsset / makerAsset
+ const testOrder3 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ takerFee: new BigNumber(50),
+ });
+ it('correctly sorts by fee adjusted rate when feeRate is Provided', async () => {
+ const orders = [testOrder1, testOrder2, testOrder3];
+ const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders, feeRate);
+ expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]);
+ });
+ it('correctly sorts by fee adjusted rate when no feeRate is Provided', async () => {
+ const orders = [testOrder1, testOrder2, testOrder3];
+ const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders);
+ expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]);
+ });
+ });
+ describe('#sortFeeOrdersByFeeAdjustedRate', () => {
+ // rate: 200 takerAsset / makerAsset
+ const testOrder1 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ takerFee: new BigNumber(99),
+ });
+ // rate: 1 takerAsset / makerAsset
+ const testOrder2 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(100),
+ });
+ // rate: 4 takerAsset / makerAsset
+ const testOrder3 = testOrderFactory.generateTestSignedOrder({
+ makerAssetAmount: new BigNumber(100),
+ takerAssetAmount: new BigNumber(200),
+ takerFee: new BigNumber(50),
+ });
+ it('correctly sorts by fee adjusted rate', async () => {
+ const orders = [testOrder1, testOrder2, testOrder3];
+ const sortedOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate(orders);
+ expect(sortedOrders).to.deep.equal([testOrder2, testOrder3, testOrder1]);
+ });
+ });
+});