aboutsummaryrefslogtreecommitdiffstats
path: root/src/contract_wrappers/exchange_wrapper.ts
diff options
context:
space:
mode:
authorLeonid <logvinov.leon@gmail.com>2017-06-07 18:22:05 +0800
committerGitHub <noreply@github.com>2017-06-07 18:22:05 +0800
commit28d3528e42563f95255cee3bd7f85cc03141522e (patch)
tree9d9119c79f1ad4f1b097253ddc7ee4cac2415e58 /src/contract_wrappers/exchange_wrapper.ts
parent8ec3bec5b3de726fbf2cc828e179ac2ed1029d9f (diff)
parent8ec2f685abefd77186b9bad5d67c9b23a9c03acf (diff)
downloaddexon-0x-contracts-28d3528e42563f95255cee3bd7f85cc03141522e.tar.gz
dexon-0x-contracts-28d3528e42563f95255cee3bd7f85cc03141522e.tar.zst
dexon-0x-contracts-28d3528e42563f95255cee3bd7f85cc03141522e.zip
Merge pull request #40 from 0xProject/cancelAsync
Add cancelOrderAsync
Diffstat (limited to 'src/contract_wrappers/exchange_wrapper.ts')
-rw-r--r--src/contract_wrappers/exchange_wrapper.ts95
1 files changed, 76 insertions, 19 deletions
diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts
index d3a53a9f7..6f62934dc 100644
--- a/src/contract_wrappers/exchange_wrapper.ts
+++ b/src/contract_wrappers/exchange_wrapper.ts
@@ -9,9 +9,9 @@ import {
ExchangeContractErrs,
OrderValues,
OrderAddresses,
+ Order,
SignedOrder,
ContractEvent,
- ZeroExError,
ExchangeEvents,
SubscriptionOpts,
IndexFilterValues,
@@ -25,7 +25,7 @@ import {utils} from '../utils/utils';
import {ContractWrapper} from './contract_wrapper';
import * as ExchangeArtifacts from '../artifacts/Exchange.json';
import {ecSignatureSchema} from '../schemas/ec_signature_schema';
-import {signedOrderSchema} from '../schemas/order_schemas';
+import {signedOrderSchema, orderSchema} from '../schemas/order_schemas';
import {SchemaValidator} from '../utils/schema_validator';
import {constants} from '../utils/constants';
import {TokenWrapper} from './token_wrapper';
@@ -42,6 +42,24 @@ export class ExchangeWrapper extends ContractWrapper {
private exchangeContractIfExists?: ExchangeContract;
private exchangeLogEventObjs: ContractEventObj[];
private tokenWrapper: TokenWrapper;
+ private static getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] {
+ const orderAddresses: OrderAddresses = [
+ order.maker,
+ order.taker,
+ order.makerTokenAddress,
+ order.takerTokenAddress,
+ order.feeRecipient,
+ ];
+ const orderValues: OrderValues = [
+ order.makerTokenAmount,
+ order.takerTokenAmount,
+ order.makerFee,
+ order.takerFee,
+ order.expirationUnixTimestampSec,
+ order.salt,
+ ];
+ return [orderAddresses, orderValues];
+ }
constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) {
super(web3Wrapper);
this.tokenWrapper = tokenWrapper;
@@ -126,21 +144,7 @@ export class ExchangeWrapper extends ContractWrapper {
const exchangeInstance = await this.getExchangeContractAsync();
await this.validateFillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, takerAddress);
- const orderAddresses: OrderAddresses = [
- signedOrder.maker,
- signedOrder.taker,
- signedOrder.makerTokenAddress,
- signedOrder.takerTokenAddress,
- signedOrder.feeRecipient,
- ];
- const orderValues: OrderValues = [
- signedOrder.makerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFee,
- signedOrder.takerFee,
- signedOrder.expirationUnixTimestampSec,
- signedOrder.salt,
- ];
+ const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(signedOrder);
const gas = await exchangeInstance.fill.estimateGas(
orderAddresses,
orderValues,
@@ -169,6 +173,39 @@ export class ExchangeWrapper extends ContractWrapper {
this.throwErrorLogsAsErrors(response.logs);
}
/**
+ * Cancel a given fill amount of an order. Cancellations are cumulative.
+ */
+ public async cancelOrderAsync(order: Order|SignedOrder, takerTokenCancelAmount: BigNumber.BigNumber): Promise<void> {
+ assert.doesConformToSchema('order',
+ SchemaValidator.convertToJSONSchemaCompatibleObject(order as object),
+ orderSchema);
+ assert.isBigNumber('takerTokenCancelAmount', takerTokenCancelAmount);
+ await assert.isSenderAddressAvailableAsync(this.web3Wrapper, 'order.maker', order.maker);
+
+ const exchangeInstance = await this.getExchangeContractAsync();
+ await this.validateCancelOrderAndThrowIfInvalidAsync(order, takerTokenCancelAmount);
+
+ const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order);
+ const gas = await exchangeInstance.cancel.estimateGas(
+ orderAddresses,
+ orderValues,
+ takerTokenCancelAmount,
+ {
+ from: order.maker,
+ },
+ );
+ const response: ContractResponse = await exchangeInstance.cancel(
+ orderAddresses,
+ orderValues,
+ takerTokenCancelAmount,
+ {
+ from: order.maker,
+ gas,
+ },
+ );
+ this.throwErrorLogsAsErrors(response.logs);
+ }
+ /**
* Subscribe to an event type emitted by the Exchange smart contract
*/
public async subscribeAsync(eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts,
@@ -194,6 +231,12 @@ export class ExchangeWrapper extends ContractWrapper {
logEventObj.watch(callback);
this.exchangeLogEventObjs.push(logEventObj);
}
+ private async getOrderHashAsync(order: Order|SignedOrder): Promise<string> {
+ const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order);
+ const exchangeInstance = await this.getExchangeContractAsync();
+ const orderHash = utils.getOrderHashHex(order, exchangeInstance.address);
+ return orderHash;
+ }
private async stopWatchingExchangeLogEventsAsync() {
const stopWatchingPromises = _.map(this.exchangeLogEventObjs, logEventObj => {
return promisify(logEventObj.stopWatching, logEventObj)();
@@ -210,7 +253,7 @@ export class ExchangeWrapper extends ContractWrapper {
if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) {
throw new Error(ExchangeContractErrs.TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER);
}
- const currentUnixTimestampSec = Date.now() / 1000;
+ const currentUnixTimestampSec = utils.getCurrentUnixTimestamp();
if (signedOrder.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
throw new Error(ExchangeContractErrs.ORDER_FILL_EXPIRED);
}
@@ -225,7 +268,21 @@ export class ExchangeWrapper extends ContractWrapper {
throw new Error(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR);
}
}
-
+ private async validateCancelOrderAndThrowIfInvalidAsync(
+ order: Order, takerTokenCancelAmount: BigNumber.BigNumber): Promise<void> {
+ if (takerTokenCancelAmount.eq(0)) {
+ throw new Error(ExchangeContractErrs.ORDER_CANCEL_AMOUNT_ZERO);
+ }
+ const orderHash = await this.getOrderHashAsync(order);
+ const unavailableAmount = await this.getUnavailableTakerAmountAsync(orderHash);
+ if (order.takerTokenAmount.minus(unavailableAmount).eq(0)) {
+ throw new Error(ExchangeContractErrs.ORDER_ALREADY_CANCELLED_OR_FILLED);
+ }
+ const currentUnixTimestampSec = utils.getCurrentUnixTimestamp();
+ if (order.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
+ throw new Error(ExchangeContractErrs.ORDER_CANCEL_EXPIRED);
+ }
+ }
/**
* This method does not currently validate the edge-case where the makerToken or takerToken is also the token used
* to pay fees (ZRX). It is possible for them to have enough for fees and the transfer but not both.