diff options
-rw-r--r-- | src/contract_wrappers/exchange_wrapper.ts | 53 | ||||
-rw-r--r-- | src/types.ts | 6 | ||||
-rw-r--r-- | test/exchange_wrapper_test.ts | 30 | ||||
-rw-r--r-- | test/utils/order_factory.ts | 4 |
4 files changed, 88 insertions, 5 deletions
diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index d3a53a9f7..982a8c0c1 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, @@ -169,6 +169,53 @@ export class ExchangeWrapper extends ContractWrapper { this.throwErrorLogsAsErrors(response.logs); } /** + * Cancels the order. + */ + public async cancelOrderAsync(order: Order, cancelAmount: BigNumber.BigNumber): Promise<void> { + assert.doesConformToSchema('order', + SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), + signedOrderSchema); + assert.isBigNumber('cancelAmount', cancelAmount); + await assert.isSenderAddressAvailableAsync(this.web3Wrapper, 'order.maker', order.maker); + + const exchangeInstance = await this.getExchangeContractAsync(); + await this.validateCancelOrderAndThrowIfInvalidAsync(order, cancelAmount); + + 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, + ]; + const gas = await exchangeInstance.cancel.estimateGas( + orderAddresses, + orderValues, + cancelAmount, + { + from: order.maker, + }, + ); + const response: ContractResponse = await exchangeInstance.cancel( + orderAddresses, + orderValues, + cancelAmount, + { + 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, @@ -225,6 +272,10 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR); } } + private async validateCancelOrderAndThrowIfInvalidAsync(order: Order, + cancelAmount: BigNumber.BigNumber): Promise<void> { + // TODO + } /** * This method does not currently validate the edge-case where the makerToken or takerToken is also the token used diff --git a/src/types.ts b/src/types.ts index a02bd0252..f2214ba6b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -68,6 +68,12 @@ export interface ExchangeContract { estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, shouldCheckTransfer: boolean, v: number, r: string, s: string, txOpts: TxOpts) => number; }; + cancel: { + (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/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 370e741b4..48d10c1e4 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -4,13 +4,13 @@ import * as Web3 from 'web3'; import * as BigNumber from 'bignumber.js'; import {chaiSetup} from './utils/chai_setup'; import ChaiBigNumber = require('chai-bignumber'); -import * as chaiAsPromised from 'chai-as-promised'; import promisify = require('es6-promisify'); import {web3Factory} from './utils/web3_factory'; import {ZeroEx} from '../src/0x.js'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; import { Token, + Order, SignedOrder, SubscriptionOpts, ExchangeEvents, @@ -323,6 +323,34 @@ describe('ExchangeWrapper', () => { }); }); }); + describe('#cancelOrderAsync', () => { + let makerTokenAddress: string; + let takerTokenAddress: string; + let coinbase: string; + let makerAddress: string; + let takerAddress: string; + const fillableAmount = new BigNumber(5); + let signedOrder: SignedOrder; + let orderHashHex: string; + before(async () => { + [coinbase, makerAddress, takerAddress] = userAddresses; + const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens(); + makerTokenAddress = makerToken.address; + takerTokenAddress = takerToken.address; + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, + ); + orderHashHex = await zeroEx.getOrderHashHexAsync(signedOrder); + }); + describe('successful cancels', () => { + it('should cancel an order', async () => { + const cancelAmount = new BigNumber(5); + await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount); + const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex); + expect(cancelledAmount).to.be.bignumber.equal(cancelAmount); + }); + }); + }); describe('tests that require partially filled order', () => { let makerTokenAddress: string; let takerTokenAddress: string; diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index 6f5fa7286..a1cc243c6 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -1,9 +1,7 @@ import * as _ from 'lodash'; import * as BigNumber from 'bignumber.js'; -import {SignedOrder, Token} from '../../src/types'; +import {SignedOrder} from '../../src/types'; import {ZeroEx} from '../../src/0x.js'; -import {constants} from './constants'; -import * as ExchangeArtifacts from '../../src/artifacts/Exchange.json'; export const orderFactory = { async createSignedOrderAsync( |