* generate wrappers in @0x/contract-wrappers and delete abi-gen-wrappers * trim exports from contract-wrappers * separate contract-wrappers tests to get rid of dependency cycle * remove dummy token contracts * temporarily skip coordinator test until we can upgrade coordinator server
97 lines
4.5 KiB
TypeScript
97 lines
4.5 KiB
TypeScript
import { DevUtilsContract } from '@0x/contract-wrappers';
|
|
import { orderCalculationUtils } from '@0x/order-utils';
|
|
import { OrderStatus, SignedOrder } from '@0x/types';
|
|
import * as _ from 'lodash';
|
|
|
|
import { constants } from '../constants';
|
|
import { OrderPrunerOnChainMetadata, OrderPrunerOpts, OrderPrunerPermittedFeeTypes, PrunedSignedOrder } from '../types';
|
|
import { utils } from '../utils/utils';
|
|
|
|
export class OrderPruner {
|
|
public readonly expiryBufferMs: number;
|
|
public readonly permittedOrderFeeTypes: Set<OrderPrunerPermittedFeeTypes>;
|
|
private readonly _devUtils: DevUtilsContract;
|
|
|
|
// TODO(dave4506): OrderPruneCalculator can be more powerful if it takes in a specified takerAddress
|
|
constructor(devUtils: DevUtilsContract, opts: Partial<OrderPrunerOpts> = {}) {
|
|
const { expiryBufferMs, permittedOrderFeeTypes } = _.assign({}, constants.DEFAULT_ORDER_PRUNER_OPTS, opts);
|
|
|
|
this.expiryBufferMs = expiryBufferMs;
|
|
this.permittedOrderFeeTypes = permittedOrderFeeTypes;
|
|
this._devUtils = devUtils;
|
|
}
|
|
|
|
public async pruneSignedOrdersAsync(signedOrders: SignedOrder[]): Promise<PrunedSignedOrder[]> {
|
|
const unsortedOrders = this._filterForUsableOrders(signedOrders, this.expiryBufferMs);
|
|
|
|
const signatures = _.map(unsortedOrders, o => o.signature);
|
|
const [ordersInfo, fillableTakerAssetAmounts, isValidSignatures] = await this._devUtils
|
|
.getOrderRelevantStates(unsortedOrders, signatures)
|
|
.callAsync();
|
|
const ordersOnChainMetadata: OrderPrunerOnChainMetadata[] = ordersInfo.map((orderInfo, index) => {
|
|
return {
|
|
...orderInfo,
|
|
fillableTakerAssetAmount: fillableTakerAssetAmounts[index],
|
|
isValidSignature: isValidSignatures[index],
|
|
};
|
|
});
|
|
// take orders + on chain information and find the valid orders and fillable makerAsset or takerAsset amounts
|
|
const prunedOrders = this._filterForFillableAndPermittedFeeTypeOrders(unsortedOrders, ordersOnChainMetadata);
|
|
|
|
return prunedOrders;
|
|
}
|
|
|
|
// tslint:disable-next-line: prefer-function-over-method
|
|
private _filterForFillableAndPermittedFeeTypeOrders(
|
|
orders: SignedOrder[],
|
|
ordersOnChainMetadata: OrderPrunerOnChainMetadata[],
|
|
): PrunedSignedOrder[] {
|
|
const result = _.chain(orders)
|
|
.filter(
|
|
(order: SignedOrder, index: number): boolean => {
|
|
const { isValidSignature, orderStatus } = ordersOnChainMetadata[index];
|
|
return (
|
|
isValidSignature &&
|
|
orderStatus === OrderStatus.Fillable &&
|
|
((this.permittedOrderFeeTypes.has(OrderPrunerPermittedFeeTypes.NoFees) &&
|
|
order.takerFee.eq(constants.ZERO_AMOUNT)) ||
|
|
(this.permittedOrderFeeTypes.has(OrderPrunerPermittedFeeTypes.TakerDenominatedTakerFee) &&
|
|
utils.isOrderTakerFeePayableWithTakerAsset(order)) ||
|
|
(this.permittedOrderFeeTypes.has(OrderPrunerPermittedFeeTypes.MakerDenominatedTakerFee) &&
|
|
utils.isOrderTakerFeePayableWithMakerAsset(order)))
|
|
);
|
|
},
|
|
)
|
|
.map(
|
|
(order: SignedOrder, index: number): PrunedSignedOrder => {
|
|
const { fillableTakerAssetAmount } = ordersOnChainMetadata[index];
|
|
return {
|
|
...order,
|
|
fillableTakerAssetAmount,
|
|
fillableMakerAssetAmount: orderCalculationUtils.getMakerFillAmount(
|
|
order,
|
|
fillableTakerAssetAmount,
|
|
),
|
|
fillableTakerFeeAmount: orderCalculationUtils.getTakerFeeAmount(
|
|
order,
|
|
fillableTakerAssetAmount,
|
|
),
|
|
};
|
|
},
|
|
)
|
|
.value();
|
|
return result;
|
|
}
|
|
|
|
// tslint:disable-next-line: prefer-function-over-method
|
|
private _filterForUsableOrders(orders: SignedOrder[], expiryBufferMs: number): SignedOrder[] {
|
|
const result = _.filter(orders, order => {
|
|
return (
|
|
orderCalculationUtils.isOpenOrder(order) &&
|
|
!orderCalculationUtils.willOrderExpire(order, expiryBufferMs / constants.ONE_SECOND_MS)
|
|
);
|
|
});
|
|
return result;
|
|
}
|
|
}
|