From 8aa673aabe292e7d4684f7cc98ec6ef2ea55ca09 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 6 Jun 2017 15:36:07 +0200 Subject: Add initial implementation with success test --- src/contract_wrappers/exchange_wrapper.ts | 53 ++++++++++++++++++++++++++++++- src/types.ts | 6 ++++ 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index d3a53a9f7..b8e34b9e8 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, @@ -168,6 +168,53 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } + /** + * Cancels the order. + */ + public async cancelOrderAsync(order: Order, cancelAmount: BigNumber.BigNumber): Promise { + assert.doesConformToSchema('order', + SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), + signedOrderSchema); + assert.isBigNumber('cancelAmount', cancelAmount); + await assert.isSenderAddressAvailableAsync(this.web3Wrapper, 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 */ @@ -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 { + // 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; }; -- cgit v1.2.3 From 08b7c24bbf23685814c5bba5148577022e40e8b0 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 6 Jun 2017 15:48:47 +0200 Subject: Fix tests --- src/contract_wrappers/exchange_wrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index b8e34b9e8..982a8c0c1 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -176,7 +176,7 @@ export class ExchangeWrapper extends ContractWrapper { SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), signedOrderSchema); assert.isBigNumber('cancelAmount', cancelAmount); - await assert.isSenderAddressAvailableAsync(this.web3Wrapper, order.maker); + await assert.isSenderAddressAvailableAsync(this.web3Wrapper, 'order.maker', order.maker); const exchangeInstance = await this.getExchangeContractAsync(); await this.validateCancelOrderAndThrowIfInvalidAsync(order, cancelAmount); -- cgit v1.2.3 From fa910bca0ebcc71e5fd7aa656972d77bec08c9e5 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 6 Jun 2017 16:57:13 +0200 Subject: Add checks and tests for expired order and zero fill amount --- src/contract_wrappers/exchange_wrapper.ts | 8 +++++++- src/types.ts | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 982a8c0c1..b5d5152dd 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -274,7 +274,13 @@ export class ExchangeWrapper extends ContractWrapper { } private async validateCancelOrderAndThrowIfInvalidAsync(order: Order, cancelAmount: BigNumber.BigNumber): Promise { - // TODO + if (cancelAmount.eq(0)) { + throw new Error(ExchangeContractErrs.ORDER_CANCEL_AMOUNT_ZERO); + } + const currentUnixTimestampSec = Date.now() / 1000; + if (order.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) { + throw new Error(ExchangeContractErrs.ORDER_CANCEL_EXPIRED); + } } /** diff --git a/src/types.ts b/src/types.ts index f2214ba6b..32148df7e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -121,6 +121,8 @@ export enum ExchangeContractErrCodes { export const ExchangeContractErrs = strEnum([ 'ORDER_FILL_EXPIRED', + 'ORDER_CANCEL_EXPIRED', + 'ORDER_CANCEL_AMOUNT_ZERO', 'ORDER_REMAINING_FILL_AMOUNT_ZERO', 'ORDER_FILL_ROUNDING_ERROR', 'FILL_BALANCE_ALLOWANCE_ERROR', -- cgit v1.2.3 From 42b4952693b66d722fa541af4a2ae9034c1cd3e7 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 6 Jun 2017 17:26:16 +0200 Subject: Add test when the order was already cancelled or filled --- src/contract_wrappers/exchange_wrapper.ts | 66 ++++++++++++++++--------------- src/types.ts | 4 ++ 2 files changed, 39 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index b5d5152dd..4b7bd172f 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -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, @@ -181,21 +185,7 @@ export class ExchangeWrapper extends ContractWrapper { 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 [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order); const gas = await exchangeInstance.cancel.estimateGas( orderAddresses, orderValues, @@ -241,6 +231,16 @@ export class ExchangeWrapper extends ContractWrapper { logEventObj.watch(callback); this.exchangeLogEventObjs.push(logEventObj); } + + /** + * Get order hash + */ + public async getOrderHashAsync(order: Order): Promise { + const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order); + const exchangeInstance = await this.getExchangeContractAsync(); + const orderHash = await exchangeInstance.getOrderHash.call(orderAddresses, orderValues); + return orderHash; + } private async stopWatchingExchangeLogEventsAsync() { const stopWatchingPromises = _.map(this.exchangeLogEventObjs, logEventObj => { return promisify(logEventObj.stopWatching, logEventObj)(); @@ -277,12 +277,16 @@ export class ExchangeWrapper extends ContractWrapper { if (cancelAmount.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 = Date.now() / 1000; 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. diff --git a/src/types.ts b/src/types.ts index 32148df7e..a89c27576 100644 --- a/src/types.ts +++ b/src/types.ts @@ -80,6 +80,9 @@ export interface ExchangeContract { cancelled: { call: (orderHash: string) => BigNumber.BigNumber; }; + getOrderHash: { + call: (orderAddresses: OrderAddresses, orderValues: OrderValues) => string; + } } export interface TokenContract { @@ -123,6 +126,7 @@ export const ExchangeContractErrs = strEnum([ 'ORDER_FILL_EXPIRED', 'ORDER_CANCEL_EXPIRED', 'ORDER_CANCEL_AMOUNT_ZERO', + 'ORDER_ALREADY_CANCELLED_OR_FILLED', 'ORDER_REMAINING_FILL_AMOUNT_ZERO', 'ORDER_FILL_ROUNDING_ERROR', 'FILL_BALANCE_ALLOWANCE_ERROR', -- cgit v1.2.3 From bfa7872b145351b66bf1c84b1f1e1a7d1bc54bad Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 6 Jun 2017 17:38:03 +0200 Subject: Add missing semicolon --- src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.ts b/src/types.ts index a89c27576..92cafd409 100644 --- a/src/types.ts +++ b/src/types.ts @@ -82,7 +82,7 @@ export interface ExchangeContract { }; getOrderHash: { call: (orderAddresses: OrderAddresses, orderValues: OrderValues) => string; - } + }; } export interface TokenContract { -- cgit v1.2.3 From 9daca6a4be95a87a63e293300d0768e3e63162d2 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 7 Jun 2017 11:04:42 +0200 Subject: Address feedback --- src/0x.js.ts | 28 ++----------------------- src/contract_wrappers/exchange_wrapper.ts | 31 +++++++++++++-------------- src/types.ts | 9 +++++--- src/utils/utils.ts | 35 +++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/0x.js.ts b/src/0x.js.ts index 0f437e039..eb7698bd4 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -4,21 +4,18 @@ import {bigNumberConfigs} from './bignumber_config'; import * as ethUtil from 'ethereumjs-util'; import contract = require('truffle-contract'); import * as Web3 from 'web3'; -import * as ethABI from 'ethereumjs-abi'; import findVersions = require('find-versions'); import compareVersions = require('compare-versions'); import {Web3Wrapper} from './web3_wrapper'; import {constants} from './utils/constants'; import {utils} from './utils/utils'; import {assert} from './utils/assert'; -import {SchemaValidator} from './utils/schema_validator'; import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper'; import {ecSignatureSchema} from './schemas/ec_signature_schema'; import {TokenWrapper} from './contract_wrappers/token_wrapper'; -import {SolidityTypes, ECSignature, ZeroExError} from './types'; +import {ECSignature, ZeroExError} from './types'; import {Order, SignedOrder} from './types'; -import {orderSchema} from './schemas/order_schemas'; import * as ExchangeArtifacts from './artifacts/Exchange.json'; // Customize our BigNumber instances @@ -133,28 +130,7 @@ export class ZeroEx { */ public async getOrderHashHexAsync(order: Order|SignedOrder): Promise { const exchangeContractAddr = await this.getExchangeAddressAsync(); - assert.doesConformToSchema('order', - SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), - orderSchema); - - const orderParts = [ - {value: exchangeContractAddr, type: SolidityTypes.address}, - {value: order.maker, type: SolidityTypes.address}, - {value: order.taker, type: SolidityTypes.address}, - {value: order.makerTokenAddress, type: SolidityTypes.address}, - {value: order.takerTokenAddress, type: SolidityTypes.address}, - {value: order.feeRecipient, type: SolidityTypes.address}, - {value: utils.bigNumberToBN(order.makerTokenAmount), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(order.takerTokenAmount), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(order.makerFee), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(order.takerFee), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(order.expirationUnixTimestampSec), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(order.salt), type: SolidityTypes.uint256}, - ]; - const types = _.map(orderParts, o => o.type); - const values = _.map(orderParts, o => o.value); - const hashBuff = ethABI.soliditySHA3(types, values); - const hashHex = ethUtil.bufferToHex(hashBuff); + const hashHex = utils.getOrderHashHex(order, exchangeContractAddr); return hashHex; } /** diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 4b7bd172f..537eb08a4 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -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'; @@ -173,23 +173,23 @@ export class ExchangeWrapper extends ContractWrapper { this.throwErrorLogsAsErrors(response.logs); } /** - * Cancels the order. + * Cancel a given fill amount of an order. Cancellations are cumulative. */ - public async cancelOrderAsync(order: Order, cancelAmount: BigNumber.BigNumber): Promise { + public async cancelOrderAsync(order: Order, takerTokenCancelAmount: BigNumber.BigNumber): Promise { assert.doesConformToSchema('order', SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), - signedOrderSchema); - assert.isBigNumber('cancelAmount', cancelAmount); + orderSchema); + assert.isBigNumber('takerTokenCancelAmount', takerTokenCancelAmount); await assert.isSenderAddressAvailableAsync(this.web3Wrapper, 'order.maker', order.maker); const exchangeInstance = await this.getExchangeContractAsync(); - await this.validateCancelOrderAndThrowIfInvalidAsync(order, cancelAmount); + await this.validateCancelOrderAndThrowIfInvalidAsync(order, takerTokenCancelAmount); const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order); const gas = await exchangeInstance.cancel.estimateGas( orderAddresses, orderValues, - cancelAmount, + takerTokenCancelAmount, { from: order.maker, }, @@ -197,7 +197,7 @@ export class ExchangeWrapper extends ContractWrapper { const response: ContractResponse = await exchangeInstance.cancel( orderAddresses, orderValues, - cancelAmount, + takerTokenCancelAmount, { from: order.maker, gas, @@ -231,14 +231,13 @@ export class ExchangeWrapper extends ContractWrapper { logEventObj.watch(callback); this.exchangeLogEventObjs.push(logEventObj); } - /** - * Get order hash + * Computes the orderHash for a given order and returns it as a hex encoded string. */ public async getOrderHashAsync(order: Order): Promise { const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order); const exchangeInstance = await this.getExchangeContractAsync(); - const orderHash = await exchangeInstance.getOrderHash.call(orderAddresses, orderValues); + const orderHash = utils.getOrderHashHex(order, exchangeInstance.address); return orderHash; } private async stopWatchingExchangeLogEventsAsync() { @@ -257,7 +256,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); } @@ -272,9 +271,9 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR); } } - private async validateCancelOrderAndThrowIfInvalidAsync(order: Order, - cancelAmount: BigNumber.BigNumber): Promise { - if (cancelAmount.eq(0)) { + private async validateCancelOrderAndThrowIfInvalidAsync( + order: Order, takerTokenCancelAmount: BigNumber.BigNumber): Promise { + if (takerTokenCancelAmount.eq(0)) { throw new Error(ExchangeContractErrs.ORDER_CANCEL_AMOUNT_ZERO); } const orderHash = await this.getOrderHashAsync(order); @@ -282,7 +281,7 @@ export class ExchangeWrapper extends ContractWrapper { if (order.takerTokenAmount.minus(unavailableAmount).eq(0)) { throw new Error(ExchangeContractErrs.ORDER_ALREADY_CANCELLED_OR_FILLED); } - const currentUnixTimestampSec = Date.now() / 1000; + const currentUnixTimestampSec = utils.getCurrentUnixTimestamp(); if (order.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) { throw new Error(ExchangeContractErrs.ORDER_CANCEL_EXPIRED); } diff --git a/src/types.ts b/src/types.ts index 92cafd409..fa3560ef8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -44,7 +44,10 @@ export interface ContractEventObj { } export type CreateContractEvent = (indexFilterValues: IndexFilterValues, subscriptionOpts: SubscriptionOpts) => ContractEventObj; -export interface ExchangeContract { +export interface ContractInstance { + address: string; +} +export interface ExchangeContract extends ContractInstance { isValidSignature: { call: (signerAddressHex: string, dataHex: string, v: number, r: string, s: string, txOpts?: TxOpts) => Promise; @@ -85,7 +88,7 @@ export interface ExchangeContract { }; } -export interface TokenContract { +export interface TokenContract extends ContractInstance { balanceOf: { call: (address: string) => Promise; }; @@ -98,7 +101,7 @@ export interface TokenContract { approve: (proxyAddress: string, amountInBaseUnits: BigNumber.BigNumber, txOpts: TxOpts) => void; } -export interface TokenRegistryContract { +export interface TokenRegistryContract extends ContractInstance { getTokenMetaData: { call: (address: string) => Promise; }; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 114b46f6c..4cea36127 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,5 +1,12 @@ import * as _ from 'lodash'; import * as BN from 'bn.js'; +import * as ethABI from 'ethereumjs-abi'; +import * as ethUtil from 'ethereumjs-util'; +import {orderSchema} from '../schemas/order_schemas'; +import {SchemaValidator} from './schema_validator'; +import {Order, SolidityTypes} from '../types'; +import {assert} from './assert'; +import * as BigNumber from 'bignumber.js'; export const utils = { /** @@ -25,4 +32,32 @@ export const utils = { spawnSwitchErr(name: string, value: any) { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, + getOrderHashHex(order: Order, exchangeContractAddr: string): string { + assert.doesConformToSchema('order', + SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), + orderSchema); + + const orderParts = [ + {value: exchangeContractAddr, type: SolidityTypes.address}, + {value: order.maker, type: SolidityTypes.address}, + {value: order.taker, type: SolidityTypes.address}, + {value: order.makerTokenAddress, type: SolidityTypes.address}, + {value: order.takerTokenAddress, type: SolidityTypes.address}, + {value: order.feeRecipient, type: SolidityTypes.address}, + {value: utils.bigNumberToBN(order.makerTokenAmount), type: SolidityTypes.uint256}, + {value: utils.bigNumberToBN(order.takerTokenAmount), type: SolidityTypes.uint256}, + {value: utils.bigNumberToBN(order.makerFee), type: SolidityTypes.uint256}, + {value: utils.bigNumberToBN(order.takerFee), type: SolidityTypes.uint256}, + {value: utils.bigNumberToBN(order.expirationUnixTimestampSec), type: SolidityTypes.uint256}, + {value: utils.bigNumberToBN(order.salt), type: SolidityTypes.uint256}, + ]; + const types = _.map(orderParts, o => o.type); + const values = _.map(orderParts, o => o.value); + const hashBuff = ethABI.soliditySHA3(types, values); + const hashHex = ethUtil.bufferToHex(hashBuff); + return hashHex; + }, + getCurrentUnixTimestamp(): BigNumber.BigNumber { + return new BigNumber(Date.now() / 1000); + }, }; -- cgit v1.2.3 From 02d36d7c9c5ce0ba4c3d97d60e7d5eab2e924496 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 7 Jun 2017 11:18:41 +0200 Subject: Make txOpts optional --- src/types.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/types.ts b/src/types.ts index fa3560ef8..aa699110b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -67,15 +67,15 @@ export interface ExchangeContract extends ContractInstance { }; fill: { (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, - shouldCheckTransfer: boolean, v: number, r: string, s: string, txOpts: TxOpts): ContractResponse; + shouldCheckTransfer: boolean, v: number, r: string, s: string, txOpts?: TxOpts): ContractResponse; estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, - shouldCheckTransfer: boolean, v: number, r: string, s: string, txOpts: TxOpts) => number; + shouldCheckTransfer: boolean, v: number, r: string, s: string, txOpts?: TxOpts) => number; }; cancel: { (orderAddresses: OrderAddresses, orderValues: OrderValues, cancelAmount: BigNumber.BigNumber, - txOpts: TxOpts): ContractResponse; + txOpts?: TxOpts): ContractResponse; estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues, cancelAmount: BigNumber.BigNumber, - txOpts: TxOpts) => number; + txOpts?: TxOpts) => number; }; filled: { call: (orderHash: string) => BigNumber.BigNumber; @@ -95,10 +95,10 @@ export interface TokenContract extends ContractInstance { allowance: { call: (ownerAddress: string, allowedAddress: string) => Promise; }; - transfer: (toAddress: string, amountInBaseUnits: BigNumber.BigNumber, txOpts: TxOpts) => Promise; + transfer: (toAddress: string, amountInBaseUnits: BigNumber.BigNumber, txOpts?: TxOpts) => Promise; transferFrom: (fromAddress: string, toAddress: string, amountInBaseUnits: BigNumber.BigNumber, - txOpts: TxOpts) => Promise; - approve: (proxyAddress: string, amountInBaseUnits: BigNumber.BigNumber, txOpts: TxOpts) => void; + txOpts?: TxOpts) => Promise; + approve: (proxyAddress: string, amountInBaseUnits: BigNumber.BigNumber, txOpts?: TxOpts) => void; } export interface TokenRegistryContract extends ContractInstance { -- cgit v1.2.3 From 498cc6cea12d9c7d2bb1af6b50f5609efb074734 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 7 Jun 2017 11:44:07 +0200 Subject: Use union type Order|SignedOrder --- src/contract_wrappers/exchange_wrapper.ts | 4 ++-- src/utils/utils.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 537eb08a4..fe03dbd16 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -175,7 +175,7 @@ export class ExchangeWrapper extends ContractWrapper { /** * Cancel a given fill amount of an order. Cancellations are cumulative. */ - public async cancelOrderAsync(order: Order, takerTokenCancelAmount: BigNumber.BigNumber): Promise { + public async cancelOrderAsync(order: Order|SignedOrder, takerTokenCancelAmount: BigNumber.BigNumber): Promise { assert.doesConformToSchema('order', SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), orderSchema); @@ -234,7 +234,7 @@ export class ExchangeWrapper extends ContractWrapper { /** * Computes the orderHash for a given order and returns it as a hex encoded string. */ - public async getOrderHashAsync(order: Order): Promise { + public async getOrderHashAsync(order: Order|SignedOrder): Promise { const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order); const exchangeInstance = await this.getExchangeContractAsync(); const orderHash = utils.getOrderHashHex(order, exchangeInstance.address); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 4cea36127..0da83c366 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -4,7 +4,7 @@ import * as ethABI from 'ethereumjs-abi'; import * as ethUtil from 'ethereumjs-util'; import {orderSchema} from '../schemas/order_schemas'; import {SchemaValidator} from './schema_validator'; -import {Order, SolidityTypes} from '../types'; +import {Order, SignedOrder, SolidityTypes} from '../types'; import {assert} from './assert'; import * as BigNumber from 'bignumber.js'; @@ -32,7 +32,7 @@ export const utils = { spawnSwitchErr(name: string, value: any) { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, - getOrderHashHex(order: Order, exchangeContractAddr: string): string { + getOrderHashHex(order: Order|SignedOrder, exchangeContractAddr: string): string { assert.doesConformToSchema('order', SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), orderSchema); -- cgit v1.2.3 From cf76d1da5dc4831c0d32464fb6cc29d36fa93eea Mon Sep 17 00:00:00 2001 From: Leonid Date: Wed, 7 Jun 2017 12:14:25 +0200 Subject: Update 0x.js.ts --- src/0x.js.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/0x.js.ts b/src/0x.js.ts index eb7698bd4..fa52d4ad8 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -14,8 +14,7 @@ import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper'; import {ecSignatureSchema} from './schemas/ec_signature_schema'; import {TokenWrapper} from './contract_wrappers/token_wrapper'; -import {ECSignature, ZeroExError} from './types'; -import {Order, SignedOrder} from './types'; +import {ECSignature, ZeroExError, Order, SignedOrder} from './types'; import * as ExchangeArtifacts from './artifacts/Exchange.json'; // Customize our BigNumber instances -- cgit v1.2.3 From 9a2a79a947eeb9f839a381d1ee27cad872636438 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 7 Jun 2017 12:16:07 +0200 Subject: Use ContractInstance from globals --- src/globals.d.ts | 4 +++- src/types.ts | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/globals.d.ts b/src/globals.d.ts index 164fc2386..567ba016d 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -47,7 +47,9 @@ declare module 'ethereumjs-util' { } // truffle-contract declarations -declare interface ContractInstance {} +declare interface ContractInstance { + address: string; +} declare interface ContractFactory { setProvider: (providerObj: any) => void; deployed: () => ContractInstance; diff --git a/src/types.ts b/src/types.ts index aa699110b..5407b0121 100644 --- a/src/types.ts +++ b/src/types.ts @@ -44,9 +44,6 @@ export interface ContractEventObj { } export type CreateContractEvent = (indexFilterValues: IndexFilterValues, subscriptionOpts: SubscriptionOpts) => ContractEventObj; -export interface ContractInstance { - address: string; -} export interface ExchangeContract extends ContractInstance { isValidSignature: { call: (signerAddressHex: string, dataHex: string, v: number, r: string, s: string, -- cgit v1.2.3 From 09f67322f1548b77ea3835b8a885e8c538835af8 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 7 Jun 2017 12:20:28 +0200 Subject: Remove assertions from utils methods --- src/0x.js.ts | 4 ++++ src/contract_wrappers/exchange_wrapper.ts | 5 +---- src/utils/utils.ts | 7 ------- 3 files changed, 5 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/0x.js.ts b/src/0x.js.ts index fa52d4ad8..7b53b70ea 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -16,6 +16,8 @@ import {ecSignatureSchema} from './schemas/ec_signature_schema'; import {TokenWrapper} from './contract_wrappers/token_wrapper'; import {ECSignature, ZeroExError, Order, SignedOrder} from './types'; import * as ExchangeArtifacts from './artifacts/Exchange.json'; +import {SchemaValidator} from './utils/schema_validator'; +import {orderSchema} from './schemas/order_schemas'; // Customize our BigNumber instances bigNumberConfigs.configure(); @@ -128,6 +130,8 @@ export class ZeroEx { * Computes the orderHash for a given order and returns it as a hex encoded string. */ public async getOrderHashHexAsync(order: Order|SignedOrder): Promise { + assert.doesConformToSchema( + 'order', SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), orderSchema); const exchangeContractAddr = await this.getExchangeAddressAsync(); const hashHex = utils.getOrderHashHex(order, exchangeContractAddr); return hashHex; diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index fe03dbd16..6f62934dc 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -231,10 +231,7 @@ export class ExchangeWrapper extends ContractWrapper { logEventObj.watch(callback); this.exchangeLogEventObjs.push(logEventObj); } - /** - * Computes the orderHash for a given order and returns it as a hex encoded string. - */ - public async getOrderHashAsync(order: Order|SignedOrder): Promise { + private async getOrderHashAsync(order: Order|SignedOrder): Promise { const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order); const exchangeInstance = await this.getExchangeContractAsync(); const orderHash = utils.getOrderHashHex(order, exchangeInstance.address); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 0da83c366..5786bab07 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -2,10 +2,7 @@ import * as _ from 'lodash'; import * as BN from 'bn.js'; import * as ethABI from 'ethereumjs-abi'; import * as ethUtil from 'ethereumjs-util'; -import {orderSchema} from '../schemas/order_schemas'; -import {SchemaValidator} from './schema_validator'; import {Order, SignedOrder, SolidityTypes} from '../types'; -import {assert} from './assert'; import * as BigNumber from 'bignumber.js'; export const utils = { @@ -33,10 +30,6 @@ export const utils = { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, getOrderHashHex(order: Order|SignedOrder, exchangeContractAddr: string): string { - assert.doesConformToSchema('order', - SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), - orderSchema); - const orderParts = [ {value: exchangeContractAddr, type: SolidityTypes.address}, {value: order.maker, type: SolidityTypes.address}, -- cgit v1.2.3