aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/contract_wrappers/exchange_wrapper.ts45
-rw-r--r--src/types.ts6
-rw-r--r--src/utils/assert.ts6
3 files changed, 57 insertions, 0 deletions
diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts
index 6f62934dc..b0c4295f1 100644
--- a/src/contract_wrappers/exchange_wrapper.ts
+++ b/src/contract_wrappers/exchange_wrapper.ts
@@ -206,6 +206,51 @@ export class ExchangeWrapper extends ContractWrapper {
this.throwErrorLogsAsErrors(response.logs);
}
/**
+ * Batch version of cancelOrderAsync. Atomically cancels multiple orders in a single transaction.
+ */
+ public async batchCancelOrderAsync(
+ orders: Array<Order|SignedOrder>, takerTokenCancelAmounts: BigNumber.BigNumber[]): Promise<void> {
+ const makers = _.map(orders, order => order.maker);
+ assert.isSameLength('orders', orders, 'takerTokenCancelAmounts', takerTokenCancelAmounts);
+ assert.assert(_.isEmpty(orders), 'Can not cancel an empty batch');
+ assert.assert(_.uniq(makers).length === 1, 'Can not cancel orders from multiple makers in a single batch');
+ const maker = makers[0];
+ // _.zip doesn't type check if values have different types :'(
+ const ordersAndTakerTokenCancelAmounts = _.zip<any>(orders, takerTokenCancelAmounts);
+ _.forEach(ordersAndTakerTokenCancelAmounts,
+ async ([order, takerTokenCancelAmount]: [Order|SignedOrder, BigNumber.BigNumber]) => {
+ assert.doesConformToSchema('order',
+ SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), orderSchema);
+ assert.isBigNumber('takerTokenCancelAmount', takerTokenCancelAmount);
+ await assert.isSenderAddressAvailableAsync(this.web3Wrapper, 'order.maker', order.maker);
+ await this.validateCancelOrderAndThrowIfInvalidAsync(order, takerTokenCancelAmount);
+ });
+ const exchangeInstance = await this.getExchangeContractAsync();
+ const orderAddressesAndValues = _.map(orders, order => {
+ return ExchangeWrapper.getOrderAddressesAndValues(order);
+ });
+ // _.unzip doesn't type check if values have different types :'(
+ const [orderAddresses, orderValues] = _.unzip<any>(orderAddressesAndValues);
+ const gas = await exchangeInstance.batchCancel.estimateGas(
+ orderAddresses,
+ orderValues,
+ takerTokenCancelAmounts,
+ {
+ from: maker,
+ },
+ );
+ const response: ContractResponse = await exchangeInstance.batchCancel(
+ orderAddresses,
+ orderValues,
+ takerTokenCancelAmounts,
+ {
+ from: maker,
+ gas,
+ },
+ );
+ this.throwErrorLogsAsErrors(response.logs);
+ }
+ /**
* Subscribe to an event type emitted by the Exchange smart contract
*/
public async subscribeAsync(eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts,
diff --git a/src/types.ts b/src/types.ts
index 5407b0121..6c217fe51 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -74,6 +74,12 @@ export interface ExchangeContract extends ContractInstance {
estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues, cancelAmount: BigNumber.BigNumber,
txOpts?: TxOpts) => number;
};
+ batchCancel: {
+ (orderAddresses: OrderAddresses[], orderValues: OrderValues[], cancelAmount: BigNumber.BigNumber[],
+ txOpts?: TxOpts): ContractResponse;
+ estimateGas: (orderAddresses: OrderAddresses[], orderValues: OrderValues[], cancelAmount: BigNumber.BigNumber[],
+ txOpts?: TxOpts) => number;
+ };
filled: {
call: (orderHash: string) => BigNumber.BigNumber;
};
diff --git a/src/utils/assert.ts b/src/utils/assert.ts
index 4dc6945a2..3842185bb 100644
--- a/src/utils/assert.ts
+++ b/src/utils/assert.ts
@@ -42,6 +42,12 @@ export const assert = {
const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
this.assert(!_.isEmpty(availableAddresses), 'No addresses were available on the provided web3 instance');
},
+ isSameLength(variableName1: string, value1: any[], variableName2: string, value2: any[]) {
+ const length1 = value1.length;
+ const length2 = value2.length;
+ this.assert(length1 === length2, `${variableName1} and ${variableName2} length mismatch.
+ ${length1} != ${length2}`);
+ },
isNumber(variableName: string, value: number): void {
this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value));
},